How to debug/fix CORS?

There are lot of articles on the internet on this topic but when I was getting this error, it really took long time to find out how to fix, lot of things I was trying which were not working until I finally fixed my errors. That’s why I write article on this topic even if there are many. It might happen to you also even after you read this article you will not be able to fix, so no guarantee but at least there will be a chance it might help you, maybe there is something what you have not found elsewhere.

Look carefully at the error message you are getting

What I was doing – I was seeing message with word CORS and did not pay attention to what else it writes. I automatically google something like “how to fix cors”. And getting tons of results and have to try lot of them to get something working. But turns out those messages can be different and tell at least something. One example was – error was telling that I send header more than once. It might not make sense – why it should not work if header is sent more than once. Like if I assign same value to variable more than once – I am not getting error, it useless operation to assign twice but not error, program works, at least PHP. But for some reason with CORS headers its that way. So by reading – you can come with your own solution – in this case look why you are sending header more than once. Or you can narrow google search results by searching by more exact error. Not looking at the error I think is because it feels it should be easy fix, quick find on google, and do. It is easy 5 minute fix I guess to those who are getting those errors frequently and having lot of experience with them but when you get once in few years, its not a 5 minute fix and you might get angry when you do 5 minute task for hours or days.

Check if you are sending header more than once

Here is the example of error in chrome console when you are sending header multiple times:

Access to XMLHttpRequest at 'http://localhost:8000/index.php/api/companies?lazyEvent=%7B%22first%22:0,%22rows%22:10,%22filters%22:%7B%22name%22:%7B%22value%22:%22%22,%22matchMode%22:%22contains%22%7D%7D%7D' from origin 'http://localhost:8080' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header contains multiple values ', http://localhost:8080', but only one is allowed.

So the key is “The ‘Access-Control-Allow-Origin’ header contains multiple values ‘”.

You can also see this in the response headers – there are 2 lines of “Access-Control-Allow-Origin”:

So now you have to find out why is that. Where they can come from? They can come from your code like in php maybe you have something like this:

header('Access-Control-Allow-Origin', '*');

They can come from the framework code, for example Laravel has this functionality https://github.com/fruitcake/laravel-cors .

They can come from web server like NGINX https://enable-cors.org/server_nginx.html .

So you have to figure out where you need to remove extra header sending from.

Check if there is no redirect which causes CORS error

I had an issue when sometimes url was not giving CORS error but sometimes same url was giving error. Turned out it was this: I had a validation using Laravel frawework. If there was validation error, the framework was redirecting to other page and was not adding the header which fixes CORS.

In the image above you can see – I make POST request, and next request is with red name ‘localhost’ – this was causing the CORS error. At first I did not pay attention to that second request, I thought the first one was giving me this error, I probably looked more at console and also probably did not pay much attention to error message. Later I somehow noticed that there is another request and started investigating why that happens.

I had Laravel 8 code:

$request->validate([ 
    'file' => 'required|mimes:jpg,jpeg,png|max:2048'
]);

If validation fails, I was new to Laravel 8, I did not know/think it gives exception. I think Laravel when gets exception, does not add the header.

Fixed this way:

try {
   $request->validate([ 
       'file' => 'required|mimes:jpg,jpeg,png|max:2048'
   ]);
} catch (Throwable $e) {
   return response(['error' => 'File invalid']);
}

Just catching exception, giving response, and since in Laravel there was set up automatic header adding – it started to work.

Try calling the request in a way you never get CORS error

So for example we have PHP backend running at localhost:8000 and JavaScript frontend running at localhost:8080. We do AJAX request and get the CORS error. No idea why. Especially when we know it worked previously or on my machine. Like in my case I just cloned to a different folder from the github.com which was working earlier but does not work now.

If it is GET request – you can try calling it by just pasting the URL directly to the address bar. If it is not GET, you can use program like Postman to do the request. That way you do not get CORS error. You can see interesting things. In my case it was problem that Laravel was trying to write the file but folder did not have permissions allowing to write. Probably it was again an exception and no header which fixes CORS added because of that. After changing folder permissions, problem was solved. I could not see permissions error, that’s why I did not know what to do. Not sure about the logs, where they written or not indicating about permission error.

Check if web server is allowing to reach the your code

If for example your PHP application is responsible for adding CORS headers, then it means for header to be added – the PHP application should be executed. But in some cases it is not reached because execution stops at web server. The reasons I know at the moment when this can happen:

  • Web server limiting upload file size
  • Preflight request does not allow HTTP method (PUT, DELETE, …)

I will discuss those cases below.

Check if web server is not limiting file upload size

There was a situation: I have made file upload working but sometimes I get CORS error. Turned out it was NGINX. It has default max upload size limit. If you upload bigger size, you get NGINX error without adding header which fixes CORS. Increasing max file uploads size fixes error.

Preflight request does not allow HTTP method by NGINX

So you might be experiencing a case when other methods work but for some reason DELETE request does not work. You are allowing in PHP application those request, allowing any domain. For example in Laravel you have configured to allow all methods https://github.com/fruitcake/laravel-cors#options . How can it not work?

Turned out that I still needed to add that method it in NGINX. Look for something like this in your NGINX config:

if ($request_method = OPTIONS ) {
location / {
        try_files $uri /index.php$is_args$args;

        # Preflight requests
        if ($request_method = OPTIONS ) {
          add_header "Access-Control-Allow-Origin"  * always;        
          add_header "Access-Control-Allow-Methods" "GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD";

          add_header "Access-Control-Allow-Headers" "Authorization, Origin, X-Requested-With, Content-Type, Accept";
          return 200;
        }
    }

See there is a line

add_header "Access-Control-Allow-Methods" "GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD";

So without for example DELETE in this line – my DELETE request was not working.

I do not know about Apache or other servers but if you are using those, maybe there is something similar.

Check if your code stops before the header is added

If you are using PHP for example and Laravel 8 – maybe you are adding statements like die(); when debugging? Laravel adds header at some point of execution. If that die(); is called before adding the header – you have a CORS error. Same probably is with exceptions as discussed above – when there is exception, probably Laravel does not add header and you have error. Same reasons can apply to other languages I think.

Do not use wildcard if it is not needed

This is not how to fix but about how to improve security. In the examples I use * value for “Access-Control-Allow-Origin” header. To increase security – if you know exact domain where this will be called from, only allow that domain instead of all domains. You can read about it stack overflow: What are the security risks of setting Access-Control-Allow-Origin?

Fixing CORS when you do not have access to the backend of API

I myself have not been in such situation but I see questions for this case often. In this case need to setup a proxy as I see from various resources. For example this one: https://stackoverflow.com/a/36068364/6737670 (had not tried).

If you have other api endpoints working without giving cors errors, I think it would work if you create one more endpoint. This new endpoint would make a request to that third party api which is causing CORS errors if you make request from frontend. Then take the response from that third party api and return it to your frontend. Hopefully it is clear what I mean, if not, please ask me.

Leave a comment

Your email address will not be published. Required fields are marked *