What is Cross-domain Resource Sharing (CORS)?

  • 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.
  • CORS requires both browser and server support. Currently, all browsers support this function, and Internet Explorer cannot be lower than Internet Explorer 10.
  • The entire CORS communication process is completed automatically by the browser without user participation. For developers, CORS communication is no different from same-origin AJAX communication, and the code is exactly the same. As soon as the browser discovers that an AJAX request crosses the source, it automatically adds some additional headers, and sometimes an additional request, but the user doesn’t feel it.
  • Therefore, the key to CORS communication is the server. As long as the server implements the CORS interface, cross-source communication is possible.

In sendingoptiosnReason for request

  • Browsers classify CORS requests into two categories: Simple request and not-so-simple Request.
  • As long as the following two conditions are met, it is a simple request.
    1. The request method is one of three:
      • HEAD
      • GET
      • POST
    2. HTTP headers do not exceed the following fields:
      • Accept
      • Accept-Language
      • Content-Language
      • Last-Event-ID
      • Content-type: Application/X-www-form-urlencoded, multipart/form-data, text/plain
  • Any request that does not meet both conditions is a non-simple request.
  • If the request has cross-domain resource sharing (CORS) and is not a simple request, a preflight of CORS is triggered. The request method for prechecking a request isOPTIONS.
  • In the actual development process, the token checking mechanism is adopted in the background, and the request sent by the foreground must be changedtokenIn theRequest Header, then you need to transmit custom Header information, or in the request HeaderContent-Type="application/json", will form a non-simple request.

The solution

  • Now that the problem is clear, we can set access-Control-max-age in the background to Control how long (s) the browser does not need to send prechecks on requests, thus reducing unnecessary prechecks.
  • Or demote a non-simple request to a simple one.

A simple request

The basic flow

  • For simple requests, the browser issues CORS requests directly. Specifically, add an Origin field to the header information.
GET /cors HTTP/1.1 Origin: http://api.bob.com Host: api.alice.com Accept-language: en-us Connection: Keep alive - the user-agent: Mozilla / 5.0...Copy the code
  • The Origin field indicates the source (protocol + domain name + port) from which the request is sent. Based on this value, the server decides whether to approve the request or not.
  • If Origin does not specify a licensed source, the server will return a normal HTTP response. The browser realizes that the response header does not contain the Access-Control-Allow-Origin field (more on that below), and it throws an error that is caught by XMLHttpRequest’s onError callback. Note that this error cannot be identified by the status code, because the status code for the HTTP response might be 200.
  • If Origin specifies a domain name within the license, the server returns a response with several additional 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
Copy the code
  • (1) Access – Control – Allow – Origin
    • This field is required. Its value is either the value of the Origin field at the time of the request, or an *, indicating acceptance of requests for any domain name
  • Access-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. This value can only be set to true if the server does not want the browser to send cookies.
  • Access-Control-Expose-Headers
    • This field is optional. 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. The above example specifies that getResponseHeader(‘FooBar’) can return the value of the FooBar field.

WithCredentials attribute

  • As mentioned above, 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 to specifyAccess-Control-Allow-Credentialsfield
Access-Control-Allow-Credentials: true
Copy the code
  • The developer must turn on the withCredentials attribute in the AJAX request.
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
Copy the code
  • 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 can explicitly disable the withCredentials.
xhr.withCredentials = false;
Copy the code
  • 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.

Non-simple request

Preview the request

  • CORS requests that are not simple requests are preceded by an HTTP query request, called a “preflight” request.
  • The browser asks the server if the domain name of the current web page is on the server’s license list, and what HTTP verb and header fields can be used. The browser issues a formal XMLHttpRequest request only if it receives a positive response; otherwise, an error is reported.
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...
Copy the code
  • The request method for the “precheck” request is OPTIONS, indicating that the request is being queried. In the header information, the key field is Origin, indicating which source the request came from. In addition to the Origin field, the precheck request header contains two special fields.
  • Access-Control-Request-Method
    • This field is required to list which HTTP methods are used by the browser for CORS requests, in this example PUT.
  • Access-Control-Request-Headers
    • This field is a comma-separated string that specifies the additional Header field to be sent by a browser CORS request, x-custom-header in the example above.

Response to precheck request

  • After receiving the precheck Request, the server checks the Origin, access-Control-request-method, and access-Control-request-headers fields and confirms that cross-source requests are allowed, it 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
Copy the code

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.
  • The following is a normal CORS request for the browser after the “precheck” 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...
Copy the code
  • The Origin field in the header above is automatically added by the browser.
  • The following is a normal response from the server.
Access-Control-Allow-Origin: http://api.bob.com
Content-Type: text/html; charset=utf-8
Copy the code
  • In the header above, the access-Control-Allow-Origin field is mandatory for each response.