Preface:

This paper was translated from ✋🏼🔥 CS Visualized: CORS written by Lydia Hallie. She used a large number of GIFs to explain the concept of CORS. No one has translated this paper in China, so I translated this paper on the understanding of the original text and corrected some mistakes, hoping to help you.

If you think the translation is good, you must like it, thank you, it is really important to me! 🌟

Note: The original GIFs are made in Keynote





In front-end development, we often use data from other sites. Before the front end displays this data, it must make a request to the server to get it.

Assuming that we are visiting the site https://api.mywebsite.com, click on the button sends a request to the https://api.mywebsite.com/users website for some user information:

⚠ ️ : here the author have a slip of pen, wrongly written as https://www.mywebsite.com, https://api.mywebsite.com, the diagram also have the mistake, the reader to pay attention to don’t be misled

We sent the request to the server, the server returned the JSON data we needed, and the front-end rendered the results normally.

Let’s try a different website. Use https://www.anotherwebsite.com to send the request: https://api.website.com/users

We asked for the same interface site, but this time the browser gave us an Error.

The CORS Error was just thrown by the browser. Let’s take a look at why this Error occurs and what exactly it means.

1. Same-origin policy

There is a mechanism for the same origin policy when the browser makes a network request. That is, by default, Web applications using the API can only request HTTP resources from the same domain that loaded the application.

For example, https://www.mywebsite.com request https://www.mywebsite.com/page is completely no problem. But when the resource is at a site with a different protocol, subdomain, or port, the request is cross-domain.

Currently, the same-origin policy limits three behaviors:

  • Cookie, LocalStorage, and IndexDB access is restricted
  • Unable to manipulate cross-domain DOM (common with iframe)
  • Javascript XHR and Fetch requests are limited


So why does the same-origin policy exist?

Let’s assume that if there is no same-origin policy, you accidentally click on a link to a health care article sent to you by qiaogu on wechat. The page is actually a phishing site that redirects you to an attack site embedded with an iframe that automatically loads the bank’s website and logs into your account through cookies.

Once logged in successfully, the phishing site can also control the IFrame DOM and transfer money from your credit card through a series of manipulations.

This is a serious security breach, and we don’t want our content on the Internet being accessed, let alone a site where money is involved.

This security problem can be solved by the same origin policy, which ensures that we can only access resources on the same site.

In this case, visit https://www.bank.com https://www.evilwebsite.com try cross-site resources, the same-origin policy would stop the operation, let the fishing website don’t have access to bank website data.

Having said that, what does the same-origin policy have to do with CORS?

2. Browser CORS

For security reasons, browsers restrict cross-domain HTTP requests from within scripts. XHR and Fetch, for example, follow the same origin policy. This means that Web applications using the API can only request HTTP resources from the same domain that loaded the application.

In daily business development, we often access cross-domain resources. To securely request cross-domain resources, browsers use a mechanism called CORS.

The full name of CORS is Cross-Origin Resource Sharing, which stands for cross-domain Resource Sharing. Although browsers forbid us from accessing cross-domain resources by default, we can use CORS to relax this restriction and access cross-domain resources with security.

The browser can use the CORS mechanism to permit compliant cross-domain access and block non-compliant cross-domain access. What does it do inside the browser? Let’s analyze it.

After a Web application makes a cross-domain request, the browser automatically adds an additional request header field to our HTTP header: Origin. Origin marks the source of the requested site:

GET https://api.website.com/users HTTP/1/1
Origin: / / https://www.mywebsite.com < - browser itselfCopy the code

In order for the browser to allow access to cross-domain resources, the response returned by the server also needs to be supplemented with response header fields that explicitly indicate whether the server allowed the cross-domain request.

3. CORS on the server

As server developers, we can indicate whether cross-domain requests are allowed by adding an additional response header field access-Control -* to the HTTP response. Based on these CORS response header fields, browsers can allow cross-source responses that are restricted by the same origin policy.

Although there are several CORS response header fields, there is one that must be added: Access-Control-Allow-Origin. The value of this header field specifies which sites are allowed to access resources across domains.

1 ️ ⃣ if we have to develop Access to the server, we may add Access to https://www.mywebsite.com, add the domain to the Access – Control – Allow – Origin.

This response header field is now added to the response header that the server sends back to the client. This field is added later, if we send cross-domain request from https://www.mywebsite.com, the same-origin policy will no longer limit the resources of the https://api.mywebsite.com site to return.

HTTP / 1.1 200 OK
Access-Control-Allow-Origin: https://www.mywebsite.com
Date: Fri, 11 Oct 2019 15:47 GM
Content-Length: 29
Content-Type: application/json
Server: Apache

{user: [{... }]}
Copy the code

2️ upon receiving the response returned from the server, the CORS mechanism in the browser will check whether the value of Access-Control-allow-Origin is equal to the value of Origin in request.

In this case, the Origin of the request is https://www.mywebsite.com, it and the response of Access – Control – Allow – the Origin of value is the same:

3️ browser check is passed, and the front-end successfully receives cross-domain resources.


So what happens when we try to Access these resources across domains from a site that isn’t listed in Access-Control-Allow-Origin?

As shown in the above, visit https://api.mywebsite.com cross-domain resources from https://www.anotherwebsite.com, the browser to throw out a CORS Error, through the interpretation of the above, we can read the Error message:

The 'Access-Control-Allow-Origin' header has a value
 'https://www.mywebsite.com' that is not equal 
to the supplied origin. 
Copy the code

In this case, the Origin of value is https://www.anotherwebsite.com. However, the server did not flag the site in the Access-Control-Allow-Origin response header field, the browser CORS mechanism blocked the response, and we were unable to retrieve the response data in our code.

CORS also allows us to add wildcard * as an allowed outfield, which means that the resource can be accessed by any outfield, so be aware of this special case


Access-control-allow-origin is one of the many header fields provided by the CORS mechanism. The server developer can also extend the server’s CORS policy with additional header fields to allow/disallow certain requests.

Another common response header field is access-Control-allow-methods. This specifies the HTTP methods allowed for cross-domain requests.

In the case above, only GET, POST, or PUT methods are allowed to access resources across domains. Other HTTP methods, such as PATCH and DELETE, are blocked.

If you want to know what the other CORS response header fields are and what they are used for, check out this list.

When it comes to HTTP methods like PUT, PATCH, and DELETE, CORS handles them a little differently. These non-simple requests trigger a precheck request from CORS.

4. Pre-check request

CORS has two types of requests: a simple request and a Preflight request. Whether a cross-domain request is simple or prechecked depends on a number of request headers.

When the request is a GET or POST method and does not have any custom Header fields, it is generally a simple request. Any other request, such as the PUT, PATCH, or DELETE methods, will precheck.

If you want to know what requirements a request must meet to qualify as a simple request, look at the documentation for MDN simple requests.

Having said all that, what exactly does “pre-check request” mean? Let’s talk about it.


1️ before sending the actual Request, the client will use OPTIONS method to initiate a pre-check Request, and the access-Control-request -* of the pre-check Request contains information about the actual Request we will deal with:

  • The header field access-Control-request-method tells the server what Method to use in the actual Request
  • The header field access-Control-request-HEADERS tells the server, what is the custom Request header field that will accompany the actual Request
OPTIONS https://api.mywebsite.com/user/1 HTTP / 1.1
Origin: https://www.mywebsite.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type
Copy the code

2️ server will return an HTTP response without body after receiving the precheck request, which marks the HTTP method and HTTP Header field allowed by the server:

HTTP / 1.1 204 No Content
Access-Control-Allow-Origin: https://www.mywebsite.com
Access-Control-Request-Method: GET POST PUT
Access-Control-Request-Headers: Content-Type
Copy the code

3️ browser receives pre-check response and checks whether actual requests should be allowed to be sent.

⚠️ : Access-Control-allow-headers: content-type is missed in the preceding figure

4️ if the pre-check response detection passes, the browser will send the actual request to the server, and then the server returns the resources we need.

If the prechecked response does not pass, CORS blocks cross-domain access and the actual request is never sent. Prechecking requests is a great way to prevent us from accessing or modifying resources on servers that do not have CORS policy enabled.

💡 To reduce network round-trips, we can cache precheck responses by adding an Access-Control-max-age header field to the CORS request. Browsers can use caching instead of sending new precheck requests.

Certification of 5.

An interesting feature of XHR or Fetch with CORS is that we can send identity credentials based on Cookies and HTTP authentication information. In general, browsers do not send credentials information for cross-domain XHR or Fetch requests.

Although CORS does not send Credentials by default, we can change this by adding the Access-Control-allow-Credentials CORS response header.

To include cookies and other authorization information in a cross-domain request, we need to do the following:

  • In the XHR requestwithCredentialsField set totrue
  • In the Fetch requestcredentialsSet toinclude
  • The serverAccess-Control-Allow-Credentials: trueAdd to the response header
// Browser fetch requests
fetch('https://api.mywebsite,com.users', {
  credentials: "include"
})

// Browser XHR request
let xhr = new XMLHttpRequest();
xhr.withCredentials = true;

// The server adds an authentication field
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Copy the code

With this done, we are ready to include identity credential information in cross-domain requests.

6. Summary

CORS Error can be a bit of a headache for front-end development, but following its rules, it allows us to make secure cross-domain requests in the browser.

There are many knowledge points about the same origin policy and CORS. This article only covers some key points. If you want to learn about CORS comprehensively, I recommend you to consult the MDN documentation and W3C specification.

7. The last

This article is over, if you feel good, you must point to praise and encourage oh, I wish you all study progress, work smoothly!

If you want to learn more about HTTP in a non-note-taking way, check out my previous post:

  • Does X-Forwarded-For get the real IP?
  • Should Spaces be encoded as %20 or + in HTTP requests?
  • Have you been through all of these HTTP holes?

Finally, I recommend a wave of my personal account: Egglabs, which will update some front-end technology and graphics related articles. It is unique and does not fill with water. Welcome to pay attention to it.