“This article has participated in the call for good writing activities, click to view: the back end, the big front end double track submission, 20,000 yuan prize pool waiting for you to challenge!”

The original intention of this series of articles is to “let each front-end engineer master the high frequency knowledge, for the work of power”. This is the front end of the 27th cut, I hope friends pay attention to the public number “kite”, armed with knowledge of their minds.

27.1 introduction

By default, browsers don’t allow XMLHttpRequest objects to access resources on different sites, according to the same origin policy. This can be a huge productivity constraint, so you need a mechanism to allow cross-domain access to resources. Then our hero, CORS (Cross-domain resource Sharing), comes in. Therefore, cross-domain data transmission can be carried out safely.

27.2 Overall process

The communication process of CORS is automatically completed by the browser without user participation. Its core point is the server. As long as the server implements THE CORS interface, cross-source communication can be realized. Although this is done automatically by the browser, the browser is actually divided into simple requests and non-simple requests based on the difference in the field of the request. The following is a brief description of both.

27.2.1 Simple Request

27.2.1.1 definition

A simple request is one that meets the following two conditions:

  1. The request method is one of three methods: HEAD, GET, and POST.
  2. HTTP headers do not exceed the following fields: Accept, accept-language, Content-language, last-event-id, Content-Type (its values are Application/X-www-form-urlencoded, multipart/form-d) Ata, text/plain).
27.2.1.2 process

The entire process of a simple request can be summed up in the following steps:

  1. The browser directly sends the CORS request. Specifically, it adds an Origin field in the header information, which indicates the source (protocol + domain name + port) from which the request comes. The server decides whether to approve the request based on this value.
  2. When the server receives the request, Origin determines whether the specified source is within the licensed range.
  3. If not, the server returns a normal HTTP response, and when the browser finds that the response header does not contain the Access-Control-Allow-Origin field, it knows something is wrong and throws an error that is caught by XML’s onError callback function. (Note: This error is not recognized by the status code because the status code is 200 for a normal response.)
  4. If Origin specifies a domain name within the license, Several Header fields (access-Control-allow-Origin, access-Control-allow-credentials, access-Control-expose-header, etc.) are added to the response returned by the server.
27.2.1.3 Key Fields
  1. Access-Control-Allow-Origin

Required field, which is either the Origin field value of the request or an * (to accept requests for any domain name).

  1. Access-Control-Allow-Credentials

Optional field whose value is a Boolean value indicating whether cookies are allowed to be sent. The default is not to send a Cookie value. When set to true, the server explicitly allows cookies to be included in the request and sent to the server. (Note: When sending cookies, note that the withCredentials attribute needs to be set in the Ajax request. Access-control-allow-origin cannot be set to *. You need to specify a specific domain name that corresponds to the requested page.

  1. Access-Control-Expose-Header

Optional field, when CORS requests, The getResponseHeader() method of the XMLHttpRequest object takes only six basic fields (cache-Control, Content-Language, Content-Type, Expires, Last-Modified, Pragm) A), if you want to obtain other fields must be specified in access-Control-expose-header.

27.2.2 Non-simple Requests

27.2.2.1 definition

Non-simple requests are non-simple requests. Non-simple requests are requests that have special requirements on the server, for example, the request method is PUT or Delete, or the content-Type field is application/ JSON.

27.2.2.2 process

A non-simple request is more complex than a simple request. A pre-check request is performed before a formal request is sent. The result of the pre-check request is used to determine whether to conduct subsequent formal communication.

  1. The browser initiates a precheck request, the request method is options, the request is used to ask;
  2. After receiving the pre-check Request, the server checks the Origin, Access-Control-request-Method, and access-Control-request-headers fields, and confirms that cross-source requests are allowed.
  3. If the browser denies the precheck request and returns a normal HTTP response without any CORS related header fields, the browser will assume that the server did not approve the precheck request and trigger an error.
  4. If the browser passes the “precheck” request, every normal CORS request from the browser will have the same Origin header field as a simple request, and the server will also have an Access-Control-Allow-Origin header field.
27.2.2.3 Key fields
  1. Access-Control-Request-Method

A required field that lists which HTTP methods are used for the browser’s CORS request.

  1. Access-Control-Request-Headers

This field is a comma-separated string that specifies the additional header fields that the browser will send for CORS requests.

  1. Access-Control-Allow-Methods

Required field, the value of which is a comma-separated string that identifies all methods supported by the server for cross-domain requests.

  1. Access-Control-Allow-Headers

The value is a comma-separated string indicating all header information fields supported by the server.

  1. Access-Control-Max-Age

Used to request the validity period of a precheck request, in seconds.

27.3 the

27.3.1 experiment a

Experimental purpose:

  1. Non-homology causes cross-domain problems
  2. Cross-domain is caused by browser response interception
  1. Let’s start with the browser console content

Console content display error, error content is cross-domain, this is because the port is different (one 8009 and one 8010), they are different sources, so cross-domain, verify experimental purpose 1.

  1. Next, take a look at what the server console prints

The console printed that the GET request was received, which proved that the browser’s request was sent and received normally by the server. It proved from the side that it was the browser that intercepted the response across domains, thus verifying experimental purpose 2.

27.3.2 experiment 2

The experiment purpose

  1. Configuring access-Control-allow-Origin on the server solves the cross-domain problem
  2. The browser determines whether cross-domain Access is possible by checking whether the value of the access-Control-Allow-Origin response header is equal to the value of the Origin in the request header
  1. First take a look at the request header

  2. A quick look at the response header

In theory, the Origin field in the request header indicates the source (protocol + domain + port) from which the request is coming. The server uses this value to decide whether to approve the request or not. If Origin does not specify a licensed source, the server returns a normal HTTP response. The response is indeed a normal response and does not contain the Access-Control-Allow-Origin field, but this is not enough to convince me that the browser validates this field to confirm whether cross-domain requests are allowed. So the next step is to do a comparative test by modifying the server-side code to look at the response header content.

  1. Starting with the simplest modification, adding the access-Control-Allow-Origin = “http://127.0.0.1:8009” field directly to the response header should theoretically Allow all cross-domain requests at this point.

Modified contents of server code

App.get ('/', (req, res) => {console.log('get request received!! '); Res. SetHeader (' Access - Control - Allow - Origin ', 'http://127.0.0.1:8009'); Res.send (' Get request has been processed '); })Copy the code

Response header content

Access-control-allow-origin: http://127.0.0.1:8009 = access-Control-allow-origin: http://127.0.0.1:8009 = access-Control-allow-origin: http://127.0.0.1:8009

  1. Only the Origin and access-Control-allow-Origin content responses are validated. What if the content is different?

The server code has been further modified

App.get ('/', (req, res) => {console.log('get request received!! '); Res. SetHeader (' Access - Control - Allow - Origin ', 'http://127.0.0.1:8008'); Res.send (' Get request has been processed '); })Copy the code

Response header content

The browser console is reporting an error and a cross-domain problem has occurred

Through this experiment, it can be verified that cross-domain problems can be solved by configuring the access-Control-allow-Origin field. In addition, the browser determines whether to Allow cross-domain Access by checking whether the value of the Access-Control-Allow-Origin field in the response header is equal to the value of Origin. The purpose of our experiment was achieved through this experiment.

27.3.3 experiment three

CORS requests do not send Cookie information by default. If cookies are to be sent to the server, Access-control-allow-origin specifies the domain name of the access-Control-allow-origin field. On the other hand, the withCredentials field must be included in the browser request.

  1. By looking at the request header (see the request header in Experiment 1), there is no Cookie information
  2. Code changes

The index. HTML page is modified

Axios ('http://127.0.0.1:8010', {method: 'get', withCredentials: true}).then(console.log)Copy the code

Server side code modification

App.get ('/', (req, res) => {console.log('get request received!! '); Console. log('cookie content is ', req.headers. Cookie); Res. SetHeader (' Access - Control - Allow - Origin ', 'http://127.0.0.1:8009'); res.setHeader('Access-Control-Allow-Credentials', true); res.cookie('test', 'test', {expires: new Date(Date.now() + 900000)}); Res.send (' Get request has been processed '); })Copy the code
  1. Look again at the request header content, with the cookie attached

  2. Check whether the server received the cookie message. The console information is as follows: Yes, it received the cookie message

Following the above configuration will send the request with cookie information, the previous configuration will report an error (you can verify yourself)

27.3.4 experiment four

The experiment purpose

  1. Verifying non-simple requests adds a precheck request
  2. The precheck request is an Options request
  3. The Request header carries the access-Control-request-methods and the access-Control-request-headers for non-simple requests. A normal CORS request can be sent only when access-Control-allow-methods and access-Control-allow-headers in the response header of the pre-check request match the preceding information.
  1. The first step is definitely to change the code

Index.html code

Axios ('http://127.0.0.1:8010', {method: 'post', headers: {' content-type ': 'application/json'}, data: {name: 'dog' } }).then(console.log)Copy the code

The server code is modified as follows

App.options ('/', (req, res) => {console.log(' Options request received!!! '); res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); res.setHeader('Access-Control-Max-Age', 10000); Res. send(' Options request already processed '); }); App.post ('/', (req, res) => {console.log('post request received!!! '); res.setHeader('Access-Control-Allow-Origin', '*'); Res.send (' Post request has been processed '); });Copy the code
  1. After modifying the code, do you want to see the result?

Let’s see if the browser is sending something, and it is sending something

What is the output of the server

The first request is an Options request, and the second request is a POST request. The printed content above verifies the first and second of the experimental purposes.

  1. Let’s take a closer look at the request and response headers for prechecked requests

Request header content

Response header content

Access-control-request-headers is the same as access-Control-allow-headers, and the content is returned normally (as shown in Step 2), but this is not sufficient to prove purpose 3. Now let’s say we add a header and look at the result.

  1. Add a request header manually

The index. HTML page is modified as follows

Axios ('http://127.0.0.1:8010', {method: 'post', headers: {' content-type ': 'application/json', 'Test': 'Test'}, data: { name: 'dog' } }).then(console.log)Copy the code

The browser console is reporting an error

The server received only options requests

The request header is

The response header information is

Through this experiment, it is proved that only when access-Control-request-headers is equal to access-Control-allow-headers, the pre-check Request will pass and the subsequent Request will be sent, thus achieving the third experimental purpose of this experiment.

1. If you think this article is good, share and like it so that more people can see it

2. Pay attention to the public number of kite, and the number of the Lord together to kill the front hundred