How to fix CORS Errors?

How to fix CORS Errors?

We all have encountered CORS errors in web-app development, in this article, we will understand what are these errors, what causes these errors in the first place, and how to fix these errors.

Before fixing the issue, in order to understand CORS Errors, we first need to understand what are origin and cross-origin. ORIGIN is the website identifier you are visiting currently. Origin is schema i.e. HTTP/HTTPS plus hostname. Cross-Origins Requests are requests originating from an origin for a different origin.

CORS stands for Cross-Origin Resource Sharing, these are a set of standards that governs how cross-origin requests should behave. Let's take an example to understand why CORS error occurs? Say, a website apples.com makes an API request to oranges.com, this will result in a CORS error, as the browser knows that the current origin is https://apples.com and there should not be requests made to oranges.com in normal conditions. In such a situation, the browser makes a pre-flight call which is an OPTIONS call.

Origin

Please note, that it is the browser that is detecting cross-origin requests and makes a preflight request. So old versions of chrome, internet explorer, or firefox may not even care about the cross-origin requests and may fire the request straight away. As a matter of fact, CORS can be disabled from the modern browser also, and there are extensions to do so. However, this is not recommended as CORS is a security feature.

CORS is actually a feature, not a bug.

Let's continue what happens after the browser makes the pre-flight request call. organges.com server receives the request from a different origin and now it has to decide if it wants to allow traffic from apples.com or not.  If oragnes.com decides not to serve the request, the browser throws the CORS error. Now, in order to handle the pre-flight request, special headers are sent by the both client and recipient server during request and response respectively. Let's take a look at those special headers.

Client Request Headers:

  • Origin: The Origin request header indicates the origin (scheme, hostname, and port) that caused the request.
  • Access-Control-Request-Method: This header is used by the client to let the server know which HTTP method will be used when the actual request is made. This header is necessary as the preflight request is always an OPTIONS and doesn't use the same method as the actual request.
  • Access-Control-Request-Headers: This header is used by the client to let the server know which HTTP headers the client might send when the actual request is made.

Server Response Headers:

  • Access-Control-Allow-Origin: This response header indicates whether the response can be shared with requesting code from the given origin. In our example, if oranges.com wants to support calls from apples.com, it can send this header as Access-Control-Allow-Origin: https://apples.com. This is normally set as a regex to support sub-domains as well.
  • Access-Control-Allow-Method: This header specifies the method or methods allowed when accessing the resource. This is used in response to a preflight request. The conditions under which a request is preflighted are discussed above. For example, Access-Control-Allow-Method: GET, POST. This is the complementary header for clients Access-Control-Request-Method header.
  • Access-Control-Allow-Headers: Used in response to a preflight request to indicate which HTTP headers can be used when making the actual request. This header is the server-side response to the browser's Access-Control-Request-Headers header. This is the complementary header for clients Access-Control-Request-Headers header.

Let's look at client-server interaction with pre-flight request fired first, and upon receiving 2xx for OPTIONS request with headers value set, the main request is fired.  

Image courtesy: MDN

Custom CORS Handler:

Now, we know why CORS happens and in order to fix it, the recipient server needs to respond with certain headers. Most of the languages and frameworks have tons of packages/libraries doing this for us. But if we need to implement something of our own, we can write a middleware for doing so.

from http import response


def cors_handler(request, *args, **kwargs):
    if request.method == 'OPTIONS':
        return response(
        	headers = {
            	"Access-Control-Allow-Origin": "https://apples.com",
                "Access-Control-Allow-Method": ["GET", "POST"],
                "Access-Control-Allow-Headers": request.headers["access-control-request-headers"]
            },
            status = 204
		)

    
pseudo-code for CORS middleware

If we put the above piece of code in oranges.com server, then requests coming from apples.com would be allowed for GET and POST requests and it will not result in a CORS error.

Conclusion:

So, in the article, we understood why CORS Errors happen and how we can fix them. Remember that CORS error is a security feature built-in in modern-day web browsers and the same problem won't arise if let's say you use some client like Postman. So next time you encounter the CORS error, instead of getting frustrated, just set the headers as per your requirement and the CORS error will be handled.


Cross-Origin Resource Sharing (CORS) - HTTP | MDN
Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that allows a server to indicate any origins (domain, scheme, or port) other than its own from which a browser should permit loading resources. CORS also relies on a mechanism by which browsers make a “preflight” request to the s…
Cross-origin resource sharing - Wikipedia
HTTP headers - HTTP | MDN
HTTP headers let the client and the server pass additional information with an HTTP request or response. An HTTP header consists of its case-insensitive name followed by a colon (:), then by its value. Whitespace before the value is ignored.