To understand JSONP cross – domain principle

preface

I believe many friends know what is cross-domain, for the sake of the unknown friends, here is a brief introduction, cross-domain refers to the browser cannot execute the script of other websites. It is caused by the same origin policy of the browser and is a security restriction imposed by the browser on JavaScript.

Why does JSONP appear

Due to browser security restrictions, data cannot be directly requested across domains (including different root domains, secondary domains, or different ports) unless the target domain authorizes access. So we took a different approach to implementing cross-domain requests. Remember the tags that allow the browser to make cross-domain requests:

  1. iframeThe label
  2. imgThe label
  3. linkThe label
  4. scriptThe label
  5. . If you don’t know, you need to review it. Next, let’s introduce this andJSONPWhat does it matter?

What is JSONP

JSONP is a dynamic Script tag cross-domain request technique. SRC points to the responder’s server and passes a parameter called callback, which is followed by our functionName. When a request is sent to the responder, Call (undefined,’ the data you want ‘), where ‘the data you want’ is passed in JSON format, hence the name JSONP because of the left and right padding of the JSON data. The backend code constructs and invokes XXX, the browser receives the response, calls xxx.call(undefined,’ data you want ‘), and the requester knows what data he wants.

How to use JSONP

Now let’s do a JSONP cross-domain request “server:” based on Node.

const Koa = require('koa');

const bodyParser = require("koa-bodyparser");

const { getUser } = require("./mock");

const app = new Koa();



app.use(bodyParser());





app.use(async (ctx, next) => {



  const { path: curPath } = ctx.request;



  if (curPath === '/jsonp') {

    // Set the response header

    ctx.set('Content-Type'.'application/javascript; charset=utf-8');

    ctx.set('X-Content-Type-Options'.'nosniff');

    const callback = ctx.query.callback;

    let data =  getUser(ctx.query.type);

    data = JSON.stringify(data);

    ctx.body = `${callback}(${data}) `

    console.log(ctx.query)

  }



});



console.log("Server started!")

app.listen(3030);

Copy the code

Client:

const btn: HTMLElement = document.getElementById('btn');



btn.addEventListener('click'.(a)= > {

    let url = 'http://127.0.0.1:3030/jsonp? type=all&callback=getdata';

    loadScripr(url);

},false)



function loadScripr(src: string) :void {

    const script: HTMLScriptElement = document.createElement('script');

    script.src = src;

    script.onload = (a)= > {

      // It is important to delete the script tag every time you create it dynamically, otherwise the entire page will explode

        document.body.removeChild(script)

    }

    script.onerror = (a)= > {

        console.error('Request failed');

       delete window['getdata'];

        document.body.removeChild(script)

    }

    document.body.appendChild(script);

}



function getdata(data: any) :void {// data indicates the data returned by the server

   // to do something

    alert(JSON.stringify(data))

}



  

Copy the code

Ps: The above code does not do compatibility processing, in the use of low-level browsers need to do something about it

When we send the request it will display:Something like this:

<script>

// data is the data returned by the backend

getdata(data)

</script>

Copy the code

So why does this happen? Before we answer that question, let’s take a look backhtmlHow do we introduce the outsidejsLibrary file, assuming when we introduceJQueryLibrary, we can see this field in the response headerContent-Type:application/javascript;The part circled in red in the image below, because of this field the browser will parse the response based on the type of the request header, which will execute the code inside, and then our global object will have itJQuery. As you might have noticed, when we make a request on the server we set the request header to,Content-Type :application/javascript; charset=utf-8Therefore, when the browser parses the resource, it will do the corresponding operation according to the response header, which has the following form ~

<script>

// data is the data returned by the backend

getdata(data)

</script>

Copy the code

Since function calls are globally scoped, it is important that our callback functions that receive data be “globally defined on the client side”.

4. Advantages and disadvantages of JSONP

Since JSONP is so useful, what are its advantages and disadvantages? Let’s take a look.

  1. It is not likeXMLHttpRequestObject implementedAjaxRequests are restricted by the same origin policy,JSONPCan cross the same origin policy;
  2. It is more compatible and will run in older browsers without the needXMLHttpRequestorActiveXThe support of
  3. After the request is complete, the result can be returned by calling callback. Gives permission to the callback method to the caller. This is going to be the same thing as going tocontrollerLayer and theviewThe layers finally parted. The JSONP service I provide only provides the data of the pure service, and the page rendering and subsequent view operations after the service are defined by the caller. If you have two pages that need to render the same data, you just need to have different rendering logic, both of which can use the same JSONP service.

disadvantages

  1. It only supports GET requests and does not support other types of HTTP requests such as POST (jSONP is implemented through script SRC, because browsers think they are requesting a resource, so they use GET instead)
  2. It only supports cross-domain HTTP requests and does not solve the problem of how to make JavaScript calls between two pages in different domains.
  3. Jsonp does not return various HTTP status codes when a call fails.
  4. Security. In case the service providing JSONP has a page injection vulnerability, that is, the javascript content it returns is controlled by someone. So what’s the result? Any site that calls this JSONP will have vulnerabilities. So can not control the risk under a domain name… Therefore, when using JSONP, we must ensure that the JSONP service used must be secure and trusted.
  5. The onerror function of the script tag is only defined in HTML5, and even if we do define the onerror handler, it is not easy to catch the cause of the error