What is cross-domain?

Cross-domain is not a new question, it’s also a very common interview question, many people have memorized, because of the same origin policy, CORS, etc., Cross-domain is where Access to XMLHttpRequest at ‘https://xxx.xxx.com’ from origin ‘https://xxx.xxx.com’ has been blocked by the browser console CORS policy: No ‘access-Control-allow-origin’ header is present on the requested resource.

First, only Web browsers can cross domains because the same origin policy of the browser is limiting. The same origin policy means that the domain name (also called host), port, and protocol must be the same. Otherwise, the browser determines that the request is cross-domain and rejects it. But strictly speaking, browsers don’t reject all cross-domain requests, they actually reject cross-domain reads.

The same-origin policy is not bad, it to a certain extent, ensure the safety of the browser is unable to adapt to the modern trend, the after service of the project, the different responsibilities of service scattered in different engineering, often these engineering domain name is different, but a demand may require corresponding to multiple services, then they need to call different service interface.

In what cases does cross-domain occur?

URL that whether to allow communication under the same domain name http://www.a.com/a.js http://www.a.com/b.js allows HTTP: / / http://www.a.com/lab/a.js Under the same domain name different folders allow http://www.a.com:8000/a.js http://www.a.com/script/b.js http://www.a.com/b.js the same domain name, Different ports cannot use the same domain name http://www.a.com/a.js https://www.a.com/b.js. http://www.a.com/a.js http://70.32.92.74/b.js and the corresponding IP address of the domain name are not allowed http://www.a.com/a.js http://script.a.com/b.js The primary domain is the same, but the subdomain is different. (Cookie is not allowed to access the domain.) http://www.a.com/a.js http://a.com/b.js Different secondary domain name (ditto) are not allowed (cookies this situation does not allow access) different domain name http://www.cnblogs.com/a.js, http://www.a.com/b.js Don't allowCopy the code

What is theCORS

Cross-domain resource sharing (CORS) is a mechanism that uses additional HTTP headers to tell browsers to allow Web applications running on one Origin (domain) to access specified resources from different source servers. When a resource requests a resource from a different domain, protocol, or port than the server on which the resource itself resides, the resource makes a cross-domain HTTP request. For example, an HTML page at the site http://domain-a.com requests http://domain-b.com/image.jpg via SRC . Many pages on the web load CSS stylesheets, images, scripts and other resources from different domains. For security reasons, browsers restrict cross-source HTTP requests from within scripts. For example, the XMLHttpRequest and Fetch apis follow the same origin policy. This means that Web applications using these apis can only request HTTP resources from the same domain that loaded the application, unless the response message contains the correct CORS response header.

The cross-domain resource sharing (CORS) mechanism allows Web application servers to control cross-domain access and secure cross-domain data transfer. Modern browsers support the use of CORS in API containers, such as XMLHttpRequest or Fetch, to reduce the risk associated with cross-domain HTTP requests.

However, it is not necessarily the browser that restricts cross-site requests. It is also possible that cross-site requests can be made normally, but the return result is blocked by the browser.

In “ancient times”, there are a lot of black technology to solve cross-domain, such as JSONP ah, window.name ah, document. Domain ah and so on are used, but the basic modern use is CORS cross-domain, so the above methods will not be discussed here.

From the above, the key to CORS communication is the server. As long as the server implements the CORS interface, cross-source communication is possible.

Although the focus of work in the back end, but as the front end, but also to understand the knowledge of this aspect, otherwise there will be 204 pre-request, and then the back end did not deal with the pot to the front end of the situation.

Here are some of the HTTP Response Headers that are common during CORS.

What is theAccess-Control-Allow-Origin

This is a field in the HTTP response header,

Specific format is: Access – Control – Allow – Origin: < Origin > | *.

Where, the value of the Origin parameter specifies the outdomain URI that is allowed to access the resource. For requests that do not require credentials, the server can specify the value of this field as a wildcard, indicating that requests from all domains are allowed.

If the server specifies a specific domain name rather than *, the value of the Vary field in the response header must contain Origin. This tells the client that the server returns different content for different source sites. Such as:

// Only respond to requests from http://mozilla.com access-Control-allow-Origin: http://mozilla.comCopy the code

What is theAccess-Control-Allow-Methods

This field is required, and its value is a comma-separated string indicating all methods supported by the server for cross-domain requests. Notice that all supported methods are returned, not just the one requested by the browser. This is to avoid multiple “pre-check” requests.

Access-control-allow-methods:

[,

]*

What is theAccess-Control-Allow-Headers ?

The supported request header name. The request header lists all supported headers, separated by commas.

The access-Control-allow-HEADERS field is required if the browser Request includes the access-Control-request-HEADERS field. It is also a comma-separated string indicating all header information fields supported by the server, not limited to those requested by the browser in precheck.

The format is access-Control-allow-headers:
[,
]*

What is theAccess-Control-Allow-Credentials

This field is optional. Its value is a Boolean value indicating whether cookies are allowed to be sent. By default, cookies are not included in CORS requests. If set to true, the server explicitly approves that cookies can be included in the request and sent to the server.

Normal browser requests and responses

Once the server passes the “precheck” request, every subsequent normal BROWSER CORS request will have the same Origin header field as a simple request. The server also responds with an Access-Control-Allow-Origin header field.

All right, that’s the setup. Now it’s time to talk about my pits.

Problem logs

Project background

Due to the legacy of history, the company also has three back-end languages: Java, PHP and Node.js. Because none of the back-end colleagues understand Node.js, the Node project has been front-end maintenance. The old project used Koa framework. I wrote logic on it before, and there was no problem in uploading pictures, until I used Nest framework to reconstruct and decouples the logic of background management system.

On the pit process

All requests for the new project are normal, local running is also normal, but when online, only uploading pictures is abnormal. Select * from ‘POST’; select * from ‘POST’;

I looked at the console information, combined with years of development experience (actually there is no), this is not cross-domain, so I looked at the code, main.ts already has app.enablecors (), puzzled, so Google, found that someone had encountered similar problems. Saying that some versions of Nest didn’t use CORS correctly online, resulting in the following code:

Nginx has already set the CORS cross-domain, but nginx has blocked the CORS cross-domain. (The company’s servers are load balanced through Nginx and then loaded to Node)

Then operation and maintenance boss very cooperate to help me configure nginx cross-domain, and then the tragedy, even OPTIONS can not go 😂 :

The console basically means that the CORS rules conflict and only one can be used.

The OPTIONS request was answered, but the connection was disconnected at the time of the POST request, and then asked me to try to access the port directly. The console displayed the following message:

If the source is HTTPS, you cannot request HTTP resources.

So I changed HTTPS to HTTP on the site, and the following message appeared:

I thought it was strange, because in local development, you can upload images normally. The only difference is that I use the PM2 process management tool online while I use my own Nodemon locally. To test my guess, I installed pM2 on my own computer, and ran, and then… The Bug reappeared.

So I asked the operations manager to start nodemon directly without PM2, and then the cross-domain problem that had been bothering me for a long time was “solved”. The reason for the quotation marks is that o&M does not really want to use Nodemon to manage processes, mainly because if the server goes down and cannot automatically pull up, the battle is far from over.

Then I continued to explore around PM2, read all the official documentation, but couldn’t find any key points. Frustrated, I had to check the PM2 startup configuration, and noticed this:

This is what I did when I updated the file in order to output the log, so that pM2 could not listen to it and the service would restart all the time. When I upload an image, I first save it on disk, then read the Buffer stream, then upload it to OSS, and finally delete the image on disk. The core code is as follows:

Net ::ERR_CONNECTION_RESET net::ERR_CONNECTION_RESET net::ERR_CONNECTION_RESET net::ERR_CONNECTION_RESET So I changed it to a temporary directory const uploadCachePath = ‘/ TMP /assets/uploads’; (Both Mac OS and Linux have this directory), then PM2 starts, uploads, and succeeds.

So far, the Bug that tortured me for nearly a week has finally been fixed, and the result has nothing to do with cross-domain.

episode

You may have noticed that/TMP /assets/uploads. What if you are developing on Windows? This naturally occurred to me, so I changed the pM2 startup:

However, no matter how it is changed, the above Bug is still triggered because the server is running two Node projects at the same time, and the other project has its own PM2 startup, so it feels like this configuration is overwritten by the other, and PM2 seems to be global. If there are other gods in-depth understanding of PM2 can point out.

Therefore, I discussed with the operation and maintenance manager and gave me permission to use the temporary directory for the time being, until I find a better solution to optimize it later. Anyway, I am the only one maintaining this project at present.

Other scenarios encountered

1. The server breaks down

Just when I found the solution, my younger brother ran over to ask me whether I had moved the configuration file, why the old project was cross-domain. I went to his console, and it did have Access to… has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Because I just stepped on the pit, and I haven’t touched the configuration file, so I think this is definitely not a cross-domain problem. Then I looked at the log of the server, and found that the server was being restarted all the time. Because he failed to synchronize a module, but only synchronized the routing file, the route could not find the corresponding function, so the service kept reporting errors and restarted without processing the request at all. I told him to upload the code again, problem solved.

So I guess (because I do not have permission to see the server configuration), this time is the nginx proxy, because the Node service is not accessible, so it is natural to read the CORS configuration, and then reported cross-domain error.

2. Axios self-check

When Axios creates an instance, there is a field to note:

If you do not set it to false, you get the following error:

Because of the access-Control-allow-credentials field mentioned earlier, CORS requests do not send cookies and HTTP authentication information by default. If you want to send cookies to the server, on the one hand, the server agrees:

Access-Control-Allow-Credentials: true

On the other hand, the developer must turn on the withCredentials property in the AJAX request, which Axios turns on by default withCredentials: true.

Otherwise, the browser won’t send a Cookie, even if the server agrees to do so. Or, if the server asks for a Cookie, the browser won’t handle it.

However, if the withCredentials setting is omitted, some browsers still send cookies together. In this case, you need to display withCredentials: false turned off.

Note that access-Control-allow-Origin cannot be set to an asterisk if cookies are to be sent, and must specify an explicit domain name consistent with the requested web page. At the same time, cookies still follow the same origin policy, only the Cookie set with the server domain name will be uploaded, cookies of other domain names will not be uploaded, and (cross-source) document. Cookie in the original web page code can not read cookies under the server domain name.

conclusion

If CORS is configured on the back end, Access to… has been blocked by CORS policy … The situation is roughly as follows:

  1. The proxy server is interrupted because the server suddenly restarts.
  2. The proxy server cannot read the CORS configuration because the server is down.
  3. Request plug-ins such as Axios are set upwithCredentials: true, causing the request to be authenticated first and intercepted;

Sometimes, the error message from the browser console doesn’t really tell you what the problem is, and as a front end, you need to know more about it.

The resources

Detailed explanation of Cross-domain Resource Sharing CORS – Ruan Yifeng’s network log

Front-end Cross-domain Collation

The Definitive GUIDE to HTTP – O ‘Reilly

,