Cross-domain, or cross-domain resource sharing – Cross-Origin Resource Sharing, is a W3C standard that allows browsers to issue XMLHttpRequest requests to non-same-origin servers.

What is a non-same-origin server? The definition of homology is that the protocol (HTTP/HTTPS), port(omitted port 80 / other digital port), and host (a.website.com/b.website.com/c.com) of two urls are the same. If the protocol, port, and host are different, they are non-identical.

The browser itself does not allow cross-domain resource requests, in order to ensure that each site’s user information — usually stored in cookies — cannot be accessed by other sites. Currently, in addition to cookies, localStorage and IndexDB cannot be accessed across domains. Information security is guaranteed by a strict policy that DOM cannot be fetched across domains and Ajax requests cannot be sent across domains.

But in practice, we often use the mode of front and back end separation for development, cross-domain request is inevitable, under the development mode, the same origin policy of the browser brings a lot of inconvenience.

What solutions do we have to solve the problem caused by the same origin policy?

Set up the document. The domain

In this case, the level 1 domain name is the same as the online domain name, but the level 2 domain name is not the same. What if the local request can carry the cookies of the online environment?

Can be achieved by

document.domain = 'myhostname' 
Copy the code

In subsequent same-origin checks, this setting will tell the browser that the current page wants to be allowed to read the cookie of the top-level domain name.

Now, the domain name check has passed, but usually we will use a port number in the development environment, such as 8080, 3001, etc. The port number is checked by the browser separately, after setting document.domain, the port number will be overwritten to NULL, and the online domain is not NULL.

So we usually use document.domain assignments in a way that allows cross domains, but also in the parent domain

document.domain = 'myhostname'
Copy the code

In this way, the host and port can be consistent.

This method only works for cookie reading and iframe Windows.

In a more general cookie sharing mode, when the server sets the cookie, it specifies the domain name of the cookie as.myhostname, for example:

Set-Cookie: key=value; domain=.example.com; .Copy the code

postMessage

In order to solve iframe cross-domain messaging, HTML5 introduces an API — Cross-document Messaging API.

Before this, people might have used window.name to pass messages in non-homologous pages, which was a hack.

With the new API, we can use it in a single page:

Window. PostMessage (' info 'target) / / parent window to the iframe window. The opener. PostMessage (' info' target) / / child window to the parent windowCopy the code

To send a message in the target page using:

Window.addeventlistener ('message', function(event) {function(event) {function(event) { Avoid receiving unsafe messages from other sources console.log(event.data, event.origin, event.source); },false);Copy the code

Listen for messages.

With this API, we can pass not only simple information to iframe, but also complex message objects, so that localStorage information can also be shared.

CORS

Ajax requests can only be sent to same-origin urls. We can use proxies to bypass the same-origin policy, or we can use CORS to bypass the same-origin restriction.

CORS here is a mechanism to tell the browser that some HTTP requests can access cross-domain resources by using additional HTTP header information.

The entire CORS communication process is automatically completed by the browser, and the user will not be aware of it. As soon as the browser discovers that an Ajax request crosses domains, it automatically adds some additional header information, and sometimes an additional request.

Non-simple request

For example, we often see an Options-type HTTP method in everyday development. This is because in CORS, when faced with a non-simple request, the browser will first use the OPTIONS method to initiate a pre-check request to check whether the actual request can be accepted by the server. The precheck request header information usually has:

OPTIONS /resources/post-here/ HTTP/1.1 
Origin: http://foo.example 
Access-Control-Request-Method: POST 
Access-Control-Request-Headers: Content-Type
Copy the code

After receiving the request, it will judge whether to accept the following actual request according to the request header information. If yes, it will return the corresponding:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://foo.example 
Access-Control-Allow-Methods: POST, GET, OPTIONS 
Access-Control-Allow-Headers: Content-Type 
Copy the code

If rejected, the browser will return a normal HTTP response without any CORS related header fields. The browser will print a Red Cross – domain error.

Note that the implementation of CORS requires both browser and server support, but the key is the server.

Non-simple requests were mentioned above. Browsers divide requests into two categories, simple and non-simple, and we can recognize non-simple requests as long as we can distinguish simple requests.

A simple request

It is a simple request as long as the following two conditions are met:

  • The request method is one of HEAD, GET, and POST

  • The header information does not exceed the following range:

    Accept accept-language content-language last-event-id content-type: Only application/ X-www-form-urlencoded, multipart/form-data, Text /plainCopy the code

For simple cross-domain requests, the browser does not send OPTIONS precheck requests, but simply adds the Origin field to the header information.

If Origin specifies a domain name that is allowed by the server, the response will return several more fields:

Access-Control-Allow-Origin: somehost
Access-Control-Allow-Credentials: true
Content-Type: text/html; charset=utf-8
Copy the code

In CORS requests, the getResponseHeader() method of the XMLHttpRequest object takes only six basic fields: Cache-control, Content-language, Content-Type, Expires, Last-Modified, Pragma. If you want to get other fields, you must specify access-Control-expose-headers:

Access-Control-Expose-Headers: X-xxxx
Copy the code

Cookies carry

Note that CORS requests do not send cookies by default. If cookies are to be sent, on the one hand the server needs to specify:

Access-Control-Allow-Credentials: true
Copy the code

On the other hand, ajax requests, such as the fetch header, need to set:

withCredentials: true
Copy the code

JSONP

JSONP is a simple method that works well with browsers. The basic idea is to add a Script tag to a web page and ask the server for JSON data. When the server receives the request, the data will be sent back in a named callback function.

The reason for this is that loading of JS resources is not restricted by the same origin policy.

In addition to Js resources, the following resource types are also not restricted by the same origin policy:

<link rel="stylesheet" href="..." > Images displayed via <img> multimedia resources played via <video> and <audio> Fonts introduced via @font-face via plugins embedded in <object>, <embed> and <applet> Any resource loaded with <iframe>.Copy the code

A random string is used to define the name of the callback function.

Such as:

function addScript(src) { var script = document.createElement('script') script.setAttribute("type","text/javascript") script.src = src document.body.appendChild(script) } window.onload = function () { addScript('http://hostname/api? callback=myCallbackFunc') } function myCallbackFunc(data) { console.log(data) }Copy the code

When the server receives the request, it puts the data in the argument of the callback function and returns:

myCallbackFunc({ ... some props });Copy the code

Since the script element requests a script that runs directly as code, the myCallbackFunc function is called as soon as the browser defines it. The JSON data as a parameter is a JS object and does not need to be parsed again.

But JSONP can only be used for HTTP requests with GET methods, which is more limited than CORS.

conclusion

These are some common cross-domain solutions, some of which are less commonly used as development approaches evolve, but understanding them can help us understand some of the underlying principles.