80

I have followed this step to setup my server to enable CORS. https://learn.microsoft.com/en-us/aspnet/web-api/overview/security/enabling-cross-origin-requests-in-web-api

But now in my browser dev console, I see this error message:

XMLHttpRequest cannot load https://serveraddress/abc. Response for preflight is invalid (redirect)

Do you know what can I do to fix it? I am making a CORS request in HTTPS. I think that is causing the 'preflight is invalid (redirect)' failure. But I don't know why or what is redirecting the OPTIONS request.

Thank you.

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
n179911
  • 19,547
  • 46
  • 120
  • 162

6 Answers6

164

Short answer: Ensure the request URL in your code isn’t missing a trailing slash.

A missing-trailing-slash problem is the most-common cause of the error cited in the question.

But that’s not the only cause — just the most common. Read on for more details.

When you see this error, it means your code is triggering your browser to send a CORS preflight OPTIONS request, and the server’s responding with a 3xx redirect. To avoid the error, your request needs to get a 2xx success response instead.

You may be able to adjust your code to avoid triggering browsers to send the OPTIONS request.

As far as what all’s going on in this case, it’s important to know browsers do a CORS preflight if:

  • the request method is anything other than GET, HEAD, or POST
  • you’ve set custom request headers other than Accept, Accept-Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width, or Width
  • the Content-Type request header has a value other than application/x-www-form-urlencoded, multipart/form-data, or text/plain

If you can’t change your code to avoid need for browsers to do a preflight, another option is:

  1. Check the URL in the Location response header in the response to the OPTIONS request.
  2. Change your code to make the request to that other URL directly instead.

The difference between the URLs might be something as simple as a trailing slash in the path — for example, you may need to change the URL in your code to add a trailing slash — e.g., http://localhost/api/auth/login/ (notice the trailing slash) rather than http://localhost/api/auth/login (no trailing slash) — or you might instead need to remove a trailing slash.

You can use the Network pane in browser devtools to examine the response to the OPTIONS request and to find the redirect URL in the value of the Location response header.


However, in some cases, all of the following will be true:

  • you’re not able to avoid the preflight OPTIONS
  • you’re not able to make any adjustments to the request URL
  • you’re not able to replace the request URL with a completely different URL

A common case with those conditions is when you try to work with some 3rd-party endpoint that requires an OAuth or SSO workflow that’s not intended to be used from frontend code.

In such cases — in all cases, actually — what’s essential to realize is that the response to the preflight must come from the same origin to which your frontend code sent the request.

So even if you create a server-side proxy that you control:

  1. If your browser sends a preflight OPTIONS request to your proxy.
  2. You’ve configured the proxy such that it just redirects the request to a 3rd-party endpoint.
  3. Thus, your frontend ends up receiving a response directly from that 3rd-party endpoint.

…then the preflight will fail.

In such a case ultimately your only alternative is: ensure the preflight isn’t just redirected to the 3rd-party endpoint but instead your own server-side (proxy) code receives the response from that endpoint, consumes it, and then sends a response of its own back to your frontend code.

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
  • 2
    Thanks for your answer. i will follow your advice. My app need to send Content-Type application/json to server so that is what triggers the pre-flight. And I can't change that. – n179911 Feb 12 '17 at 07:04
  • I'm trying to redirect from http to https using nginx. What to do in this case? I'm using Flask-restful. – Light Jan 25 '21 at 08:43
  • 2
    I elected to remove the trailing slash altogether from all my urls. I have suffered quite a bit due to this preflight CORS error. I would find some pages had the error whilst others didn't. What a hellish experience; for weeks at that! – andromeda Apr 30 '21 at 11:36
  • 2
    *the Content-Type request header has a value other than* [...] It's not as simple (no pun intended) as that: https://twitter.com/jub0bs/status/1432025056234835980 – jub0bs Sep 02 '21 at 20:41
  • In my case, I had to switch from HTTP to HTTPS. Fantastic post: thank you! – Hawkeye Parker Jan 31 '22 at 21:12
  • 1
    I had two slashes in the URL, like 'https://my-api.com//data' instead of 'https://my-api.com/data'. Always worked until I wanted to send custom headers (for auth). Removed the second slash. I don't know why but it works now. – Damien Flury Feb 01 '22 at 12:57
  • It was the trailing slash in my case. The backend developer had mistakenly kept a trailing slash at the end of the url. Thankyou @sideshowbarker – Arun T Feb 17 '22 at 15:49
  • checking the `Location` in the response headers was the key for me to find out that I was doing the request to `http` while it should be `https`, thank you! – Oswaldo Feb 28 '22 at 22:36
  • In my case it was a trailing slash ( I removed it ). from http://hello/?id=123 to http://hello?id=123. However this error won't show up if working on development mode (working locally), but would appear when on production mode (deployed). – mike_s Sep 04 '22 at 15:36
  • This is such a great answer and solved my issue. The Location response header had www, while my URL didn't. First answer on SO I ever save for further reference. – Mickael Bergeron Néron Sep 02 '23 at 01:25
42

This happens sometimes when you try calling an https service as http, for example when you perform a request on:

'http://example.com/api/v2/tickets'

Which should be:

'https://example.com/api/v2/tickets'

juagicre
  • 1,065
  • 30
  • 42
Adeojo Emmanuel IMM
  • 2,104
  • 1
  • 19
  • 28
15

First of all, ensure that you have "Access-Control-Allow-Origin": "*" in the headers

then just remove "/" at the end of url

e.g. change

url: "https://facebook/api/login/"

into

url: "https://facebook/api/login" (without '/')

or vice versa

  • 2
    ONLY do this if you want your endpoint to be open to EVERYONE. You can allow your own domain (and subdomains) by adding the following instead: SetEnvIf Origin "^(.*\.domain\.com)$" ORIGIN_SUB_DOMAIN=$1 Header set Access-Control-Allow-Origin "%{ORIGIN_SUB_DOMAIN}e" env=ORIGIN_SUB_DOMAIN – Wijnand May 05 '21 at 17:48
  • 1
    `"Access-Control-Allow-Origin": "*"` this could be a security risk in production, but it's okay for development. – Md. A. Apu Aug 16 '21 at 14:31
  • this kinda worked for me. now its not 404 but 500 error – ERJAN Jan 05 '23 at 10:00
5

In my case I did not have to set the request header to have "Access-Control-Allow-Origin": "*". The url HAD TO be ending with a "/" at the end

mAsK
  • 189
  • 3
  • 9
1

in my case i also solve this preflight request by just putting one slash (/) at the end of the api

#django #reactJs

Saurabh
  • 19
  • 2
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Sep 15 '22 at 13:40
  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/32681891) – GuedesBF Sep 16 '22 at 01:43
-1

The CORS request was responded to by the server with an HTTP redirect to a URL on a different origin than the original request, which is not permitted during CORS requests.

For example, if the page https://service.tld/fetchdata were requested, and the HTTP response is "301 Moved Permanently", "307 Temporary Redirect", or "308 Permanent Redirect" with a Location of https://anotherservice.net/getdata, the CORS request will fail in this manner.

To fix the problem, update your code to use the new URL as reported by the redirect, thereby avoiding the redirect.The CORS request was responded to by the server with an HTTP redirect to a URL on a different origin than the original request, which is not permitted during CORS requests.

For example, if the page https://service.tld/fetchdata were requested, and the HTTP response is "301 Moved Permanently", "307 Temporary Redirect", or "308 Permanent Redirect" with a Location of https://anotherservice.net/getdata, the CORS request will fail in this manner.

To fix the problem, update your code to use the new URL as reported by the redirect, thereby avoiding the redirect.