Cross-domain resource sharing CORS detailed explanation
CORS is a W3C standard, the full name is “Cross-origin resource sharing” (Cross-origin resource sharing).
This article introduces the internal mechanism of CORS in detail.
(Photo caption: Taken at the Oasis Park in Al Ain, UAE)
CORS needs to be supported by both the browser and the server. Currently, all browsers support this function, and IE browser cannot be lower than IE10.
The entire CORS communication process is done automatically by the browser and does not require user involvement. For developers, there is no difference between CORS communication and AJAX communication of the same origin, and the code is exactly the same. Once the browser finds that the AJAX request is cross-origin, it will automatically add some additional header information, and sometimes an additional request will be made, but the user will not feel it.
Therefore, the key to implementing CORS communication is the server. As long as the server implements the CORS interface, it can communicate across origins.
Two, two kinds of requests
Browsers divide CORS requests into two categories: simple request and not-so-simple request.
As long as the following two conditions are met at the same time, it is a simple request.
(1) The request method is one of the following three methods:
(2) HTTP header information does not exceed the following fields:
- Content-Type: three limited value
This is for compatibility with forms, because forms have historically been able to make cross-domain requests. The cross-domain design of AJAX is that as long as the form can be sent, AJAX can be sent directly.
Anything that does not meet the above two conditions at the same time is a non-simple request.
Browsers handle these two types of requests differently.
Three, simple request
3.1 Basic process
For simple requests, the browser directly issues CORS requests.
Specifically, it is to add a
in the header information
The following is an example. The browser finds that this cross-origin AJAX request is a simple request, and automatically adds a
in the header information
GET /cors HTTP/1.1 Origin: http://api.bob.com Host: api.alice.com Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0...
In the above header information, the
field is used to indicate which source (protocol + domain name + port) this request comes from.
The server decides whether to approve this request based on this value.
specified source is not within the permitted scope, the server will return a normal HTTP response.
The browser found that the header information of this response did not contain any
fields (see below for details), and knew that there was an error, and thus threw an error, which was
Note that this error cannot be identified by the status code, because the status code of the HTTP response may be 200.
specified domain name is within the permitted range, the response returned by the server will contain several more header fields.
Access-Control-Allow-Origin: http://api.bob.com Access-Control-Allow-Credentials: true Access-Control-Expose-Headers: FooBar Content-Type: text/html; charset=utf-8
Among the above header information, there are three fields related to CORS request, all
This field is required.
Its value is either the value of the
when the request is made
, or one
, which means that the request for any domain name is accepted.
This field is optional.
Its value is a Boolean value, which indicates whether to allow the sending of cookies.
By default, cookies are not included in CORS requests.
If it is set
, it means that the server clearly allows the cookie to be included in the request and sent to the server together.
This value can only be set
. If the server does not want the browser to send cookies, just delete this field.
This field is optional.
When the request CORS,
method can only get six basic
If you want to get other fields, you must
specify them in them.
The above example specifies that
the value of the field
can be returned
3.2 withCredentials attribute
As mentioned above, CORS requests do not send cookies and HTTP authentication information by default.
If you want to send the Cookie to the server, on the one hand, the server must agree and specify the
On the other hand, the developer must open the
in the AJAX request
var xhr = new XMLHttpRequest(); xhr.withCredentials = true;
Otherwise, even if the server agrees to send cookies, the browser will not send them. Or, the server requires cookies to be set, and the browser will not process it either.
However, if you omit the
setting, some browsers will still send cookies together.
At this time, it can be closed explicitly
xhr.withCredentials = false;
It should be noted that if you want to send a cookie,
you cannot set it as an asterisk, you must specify a clear domain name that is consistent with the requested page.
At the same time, cookies still follow the same-origin policy. Only cookies set with the server domain name will be uploaded, cookies of other domain names will not be uploaded, and the (cross-origin) original webpage code
cannot read the cookies under the server domain name.
Four, non-simple request
4.1 Pre-check request
Non-simple request that there are special requirements for the server request, such as is
type field is
For non-simple CORS requests, an HTTP query request will be added before the formal communication, called a “preflight” request (preflight).
The browser first asks the server whether the domain name of the current webpage is in the server’s permission list, and which HTTP verbs and header fields can be used.
Only after getting a positive answer, the browser will send a formal
request, otherwise it will report an error.
var url = 'http://api.alice.com/cors'; var xhr = new XMLHttpRequest(); xhr.open('PUT', url, true); xhr.setRequestHeader('X-Custom-Header', 'value'); xhr.send();
In the above code, the HTTP request method is
and a custom header is sent
The browser finds that this is a non-simple request, and automatically sends a “pre-check” request, asking the server to confirm that the request can be made. The following is the HTTP header information of this “preflight” request.
OPTIONS /cors HTTP/1.1 Origin: http://api.bob.com Access-Control-Request-Method: PUT Access-Control-Request-Headers: X-Custom-Header Host: api.alice.com Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0...
The request method used for the “preflight” request is
to indicate that this request is for inquiry.
In the header information, the key field is
to indicate which source the request comes from.
In addition to the
fields, the header information of the “preflight” request includes two special fields.
This field is required. It is used to list which HTTP methods will be used in the browser’s CORS request, as in the above example
This field is a comma-separated string that specifies the additional header fields that the browser will send in CORS requests, as in the above example
4.2 Response to preflight request
Server receives a “pre-screening” after the request, examined
after field, acknowledge allow cross-origin requests, we can respond.
HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 01:15:39 GMT Server: Apache/2.0.61 (Unix) Access-Control-Allow-Origin: http://api.bob.com Access-Control-Allow-Methods: GET, POST, PUT Access-Control-Allow-Headers: X-Custom-Header Content-Type: text/html; charset=utf-8 Content-Encoding: gzip Content-Length: 0 Keep-Alive: timeout=2, max=100 Connection: Keep-Alive Content-Type: text/plain
In the above HTTP response, the key is the
field, which means that
data can be requested.
This field can also be set as an asterisk, which means that any cross-origin request is agreed.
If the server denies the “preflight” request, it will return a normal HTTP response, but without any CORS-related header fields.
At this time, the browser will determine that the server does not agree to the preflight request, and therefore triggers an error, which is
The console will print out the following error message.
XMLHttpRequest cannot load http://api.alice.com. Origin http://api.bob.com is not allowed by Access-Control-Allow-Origin.
The other CORS-related fields responded by the server are as follows.
Access-Control-Allow-Methods: GET, POST, PUT Access-Control-Allow-Headers: X-Custom-Header Access-Control-Allow-Credentials: true Access-Control-Max-Age: 1728000
This field is required, and its value is a string separated by commas, indicating all cross-domain request methods supported by the server. Note that all supported methods are returned, not just the method requested by the browser. This is to avoid multiple “preflight” requests.
If the browser request includes a
field is required.
It is also a comma-separated string, indicating all header fields supported by the server, not limited to the fields requested by the browser in the “preflight”.
This field has the same meaning as in a simple request.
This field is optional and is used to specify the validity period of this pre-check request, in seconds. In the above results, the validity period is 20 days (1728000 seconds), which means that the response is allowed to be cached for 1728000 seconds (20 days). During this period, there is no need to issue another pre-check request.
4.3 Normal requests and responses from the browser
Once the server has passed the “pre-check” request, every subsequent normal CORS request from the browser will be the same as a simple request, with a
The server’s response will also have a
The following is the normal CORS request of the browser after the “preflight” request.
PUT /cors HTTP/1.1 Origin: http://api.bob.com Host: api.alice.com X-Custom-Header: value Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0...
fields of the
above header information
are automatically added by the browser.
The following is the normal response of the server.
Access-Control-Allow-Origin: http://api.bob.com Content-Type: text/html; charset=utf-8
In the above header information, the
field must be included in every response.
Five, comparison with JSONP
CORS is used for the same purpose as JSONP, but is more powerful than JSONP.
JSONP only supports
requests, CORS supports all types of HTTP requests.
The advantage of JSONP is that it supports old browsers and can request data from websites that do not support CORS.