Cross-origin resource sharing (CORS) is a mechanism for making restricted resources of a web page accessible to pages from other domains based on HTTP headers. Through this mechanism, pages can freely use images, styles, scripts, iframes, and videos from different sources (cross-origin).
In general, some cross-origin requests (especially ajax) are prohibited by the same-origin policy. CORS defines a way to allow web application servers to perform cross-origin access control, thus enabling secure cross-origin data transfer.
CORS is currently supported by almost all modern browsers and can be found at MDN for information on browser compatibility.
Browsers divide CORS requests into two categories: simple requests and not-so-simple requests. These two terms are not part of the Fetch specification.
Some requests do not trigger a CORS preflight request. Such requests are referred to as “simple requests” in this document.
A request is considered a “simple request” if it meets all of the following conditions: 1.
the request method is
HTTP headers are allowed to contain only the set of CORS-safe initial fields defined by the Fetch specification, except for those fields that are automatically set by the user agent and those defined in the Fetch specification as disabled header names.
Content-Typeis limited to three values:
XMLHttpRequestUploadobject in the request does not have any event listeners registered; the
XMLHttpRequestUploadobject can be accessed using the
ReadableStreamobject is used in the request.
Simple requests are designed to be compatible with forms, which have historically been able to make cross-domain requests.
For simple requests, the browser makes a CORS request directly. Specifically, a field named
Origin is added to the HTTP header.
In the above header, the
Origin field is used to indicate the source of this request, and the server side decides whether to grant the request based on this value.
If the source specified by
Origin is within the permitted range, the response header returned by the server will add the following fields.
Access-Control-Allow-Originfield indicates the source of the request allowed by the server, and its value is either the value of the Origin field at the time of the request or
Access-Control-Allow-Credentialsfield indicates whether the server is allowed to send credential information; this field is optional, and by default, no credential information is allowed.
Access-Control-Expose-Headersfield indicates the allowed HTTP header fields specified by the server, which is optional.
If the source specified by
Origin is not in the permitted range, the server returns a normal HTTP response without the
Access-Control-Allow-Origin field. When the browser finds that this field is not included it knows that the request is in error and will throw an exception. Note that the HTTP response code for this error may be 200 or 204, and therefore cannot be identified by the status code.
Non-simple requests - Pre-check requests
As mentioned above, CORS requests have non-simple requests in addition to simple requests. In short, non-simple requests are requests that have special requirements for the server, such as a request method of
DELETE, or the value of the
Content-Type field in the HTTP header is not one of the three “CORS-safe
Content-type field values” described above.
CORS requests that are not simple requests add an HTTP query request called a “preflight” before the formal communication.
As you can see from the above message, the browser first sends a “preflight request” using the
OPTIONS method, which is a method defined in the HTTP/1.1 protocol to obtain more information from the server. This method has no impact on the server resources. The preflight request carries both of the following prefix fields.
Access-Control-Request-Methodfield will inform the server of the method that will be used for the actual request.
Access-Control-Request-Headersfield will inform the server of the custom request header fields that will be carried by the actual request.
The server will decide accordingly whether to allow the actual request and return the appropriate response.
Access-Control-Allow-Originfield does not differ from when a simple request is made.
Access-Control-Allow-Methodsfield indicates which methods the server allows to initiate requests.
Access-Control-Allow-Headersfield indicates the additional fields the server allows to be carried in the request headers.
Access-Control-Allow-Credentialsfield does not differ from when a simple request is made.
Access-Control-Max-Agefield indicates the validity time of the response, during which the browser is not required to initiate another preflight request for the same request. Note that the browser itself maintains a maximum validity time, and if the value of this field exceeds the maximum validity time maintained by the browser, it will not take effect.
If the server “denies” a preflight request, it also returns a normal HTTP response, but does not contain any HTTP header fields related to CORS. At this point the browser assumes that the server did not agree to the preflight request and throws an error.
Once the preflight request is passed, the next steps are the same as for a simple request, so I won’t go over them here.
CORS requests with identity credentials
As mentioned above, CORS requests do not send credential information (cookies and HTTP authentication information) by default. To send credentials to the server, not only does the server need to specify the
Access-Control-Allow-Credentials field in the HTTP header, but it also needs to specify whether to send credential information when requesting.
withCredentials flag needs to be set to
true when making a CORS request to the server using
Requests made with fetch require
credentials to be set to
include in order for the browser to send a request with credentials to a cross-domain source.
Comparison with JSONP
CORS and JSONP are used for the same purpose, but CORS is more powerful than JSONP.
The disadvantage of JSONP is that it only supports GET requests, while CORS supports all types of HTTP requests. If a site needs to be compatible with older browsers or needs to request data from sites that do not support CORS, you still need to use JSONP.