How to Deal With CORS
This guide explains CORS and provides tips and strategies around debugging these types of requests.
CORS can be one of the most frustrating things to debug when working with front-end code. This guide provide steps for determining if you are having a CORS issue, ways to resolve them, and how to configure CORS on your Zesty.io instance.
CORS provides instructions by the requested server to the requesting client (your web browser) on what its rules are on requests from other domains which aren't itself. A basic example of CORS is as follows: When domain-A makes a request to domain-B, domain-B will send instructions back to domain-A stating whether or not domain-A is allowed to make that request to domain-B. We will refer to this example throughout this guide.
Those instructions act as a security mechanism to limit how data is accessed. However, it should be noted that CORS is not an absolute measure to prevent access to an API as it is up to the requesting client (domain-A) whether to respect the instructions returned by the requested server (domain-B). This means that things such as cURL (Client URL) can be used to bypass these instructions.
The "instructions" we are referring to are the HTTP headers
Access-Control-Allow-*returned when accessing a domain's URL which has a CORS policy in place.
CORS requests are known as "complex requests" which trigger a web browser (domain-A) to send a "preflight" OPTIONS request. The preflight request is an HTTP request which the browser (domain-A) makes in order to ask the requested server (domain-B) what its policy on CORS is. Based upon the response, the browser (domain-A) will then decide whether it should proceed with making the intended HTTP request. This is usually where we begin to see errors being thrown.
While CORS policies are set by the back-end server (domain-B) there are a few things that you'll want to test on the front-end (domain-A) to ensure that your request is being sent correctly.
One of the biggest "gotchas" in front-end development can be browser extensions. When installed you've given them permission to run code on the browser tabs you are viewing and as such they have the ability to modify functionality happening on a web page. Not all extensions are good actors and can cause intentional and unintentional side effects; one of those being modifying network requests. Whenever you are debugging front-end issues we always suggest using a "clean-room" profile. A "clean-room" profile is a browser profile without any extensions installed. This will ensure that you don't have any unexpected changes in behavior from 3rd party code locations.
Explicitly setting the header can cause issues. These issues will be indicated by an error in the console. For example, the error below says: Request header field skip-caching is not allowed by Access-Control-Allow-Headers in preflight response.
Access-Control-Allow-Headers failure in the Chrome console.
This means that a skip-caching header has been explicitly declared and is causing the failure. Explicitly set request headers, that are not default headers, have to be explicitly allowed by the values returned in the
Access-Control-Allow-Headersheader. If you're unsure about what allowed headers the endpoint supports, look at the preflight Options response. The values displayed on the Access-Control-Allow-Headers determines what can be used.
Whenever you need to debug front-end code your best friend will be a browser's inspector. A browser's inspector is a browser's internal tool for examining the source code and resulting behaviors of a web page.
Please be aware that not all browser inspectors are created equal and can have significant differences in available functionality; these differences can impact a user's ability to debug their code.
Most browsers' inspectors can be accessed by right-clicking on a web page to show the context menu and selecting the "inspect" option.
Opening the inspector in Chrome
This should open the inspector which will contain multiple tabs. The two we are interested in will be the "Console" and "Network" tab.
The console is where we can see errors and logs from both the browser and our page's source code.
When a CORS error occurs you should see a console error stating what the error was.
Sometimes when a server error occurs the browser will display it as a CORS error. When you see a CORS error in the console it is important to inspect the request in the Network tab and confirm the response headers.
Typically the displayed error will point out the exact header which caused the CORS failure.
Example CORS error from the console.
This information is usually enough to understand what caused the failure and what is needed to allow the request to succeed. Most commonly this is a mismatch between the origin-domain (domain-A) and requested-domain (domain-B). If your response header
Access-Control-Allow-Originvalue does not match the domain you are on, then it will fail. If this is the case you will need to communicate with the back-end server owner (domain-B) to determine a solution. For example: they would need to allow the domain (domain-A) you are requesting from.
The origin value of
Access-Control-Allowis the combination of the protocol, domain, and port.
Access-Control-Allow-Originhas a special value which can be set, an asterisk
*. This is known as a wildcard which means that the back-end server (domain-B) allows requests from any origin (domain-A). Public APIs need this value set in order to allow requests from any origin.
In addition to the
Access-Control-Allow-*headers there are also
Access-Control-Request-*headers. It's important to have a cursory understanding of the available values here to more fully understand how CORS requests are formulated. If you need more information, please refer to the CORS article linked at the top of this guide.
By using the network tab we can inspect all the network traffic to and from the domain we are on.
Chrome's inspector tool.
Note: In order to see the requests' methods you may need to right-click in the inspector and select Method from the menu shown.
Select Method from the ,menu to shown to see the Method column.
In looking at the response headers of our OPTIONS request we will be able see what
Access-Control-Allow-*were returned from our back-end server. These instructions are the instructions that the browser then follows.
Request headers in Chrome's inspector.
If the domain we are on is not shown in the
Access-Control-Allow-Originvalue then we will not be able to make the CORS request.
Most browsers' network tabs allow for filtering types of requests, such as XHR, CSS, etc. When an OPTION request fails some browsers will not make the actual request which will cause it to not appear in the filtered XHR list. For this reason it is important to be on the "All" filter to ensure you are seeing any failures which could be occurring.
When authoring code which will make a
FetchCORS request one setting you will want to be familiar with is
mode. This is the setting which explicitly states what type of request you want to make. It is useful to define this to ensure consistency in how a browser makes requests along with communicating to yourself or other, future developers what the intent and expectations of network requests are.
Since your Zesty.io instance can act as an API to front-end code you have the option of controlling how CORS requests are responded to by your instance.
Zesty.io CORS developer settings.
CORS errors can be one of the biggest points of frustration when authoring front-end code. Hopefully with this guide we have given you some helpful insights and strategies for debugging these error when they occur.