General:
Request URL:x/site.php
Request Method:OPTIONS
Status Code:302 Found
Remote Address:x.x.x.x:80
Response Headers:
view source
Access-Control-Allow-Headers:Content-Type
Access-Control-Allow-Origin:*
Access-Control-Max-Age:300
Cache-Control:no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Content-Length:0
Content-Type:text/html; charset=UTF-8
Date:Thu, 02 Mar 2017 14:27:21 GMT
Expires:Thu, 19 Nov 1981 08:52:00 GMT
Location:y
Pragma:no-cache
Server:Apache/2.4.25 (Ubuntu)
Request Headers:
view source
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:authorization
Access-Control-Request-Method:POST
Cache-Control:no-cache
Connection:keep-alive
DNT:1
Host:x
Origin:http://127.0.0.1:3000
Pragma:no-cache
Referer:http://127.0.0.1:3000/
User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.90 Safari/537.36
Apache virtualhost config looks as so:
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin "http://127.0.0.1:3000"
Header set Access-Control-Allow-Origin "http://127.0.0.1"
Header set Access-Control-Max-Age "300"
Header set Access-Control-Allow-Credentials "true"
Header set Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept"
Header set Access-Control-Allow-Methods "POST, GET, PUT, DELETE, PATCH, OPTIONS"
</IfModule>
The preflight request is skipping the apache config and hitting my webapp directly, which does a redirect (hence the 302 and the location: y).
I don't know why the preflight request is not being handled by apache?
The two main things you need to change/add are:
Header always set
instead of justHeader set
OPTIONS
by just sending back a200 OK
with those headersSo to enable the request in the question to work, here’s a minimal(ish) config snippet:
Longer explanation at https://benjaminhorn.io/code/setting-cors-cross-origin-resource-sharing-on-apache-with-correct-response-headers-allowing-everything-through/
Some general notes on what values to set for the various
Access-Control-
response headers:Access-Control-Allow-Headers
: you must set it to include any header names your request sends except CORS-safelisted header names or so-called “forbidden” header names (names of headers set by the browser that you can’t set in your JavaScript); the spec alternatively allows the*
wildcard as its value—so you can try it someday, but no browser supports it yet: Chrome bug, Firefox bug, Safari bugAccess-Control-Allow-Methods
: the spec alternatively allows the*
wildcard—but again, as withAccess-Control-Allow-Headers: *
, no browsers support it yetAccess-Control-Expose-Headers
: you must set to include any response headers your client code needs to read beyondCache-Control
,Content-Language
,Content-Type
,Expires
,Last-Modified
andPragma
—which are exposed by default (a lot of people forget to set this and end up baffled about why they can’t read the value of a particular response header); again the spec alternatively allows the*
wildcard here, but no browsers support it yetAccess-Control-Max-Age
: Chrome has an upper limit of600
(10 minutes) hardcoded, so there’s no point in setting a higher value for it than that (Firefox may respect it, but Chrome will just throttle it down to 10 minutes if you set it higher, and Safari limits it to only 5 minutes)So then, about the particular request shown in the question, here are some specific notes:
Your request has
Access-Control-Request-Headers:authorization
so in your Apache config, addAuthorization
in theAccess-Control-Allow-Headers
response header too.Origin
is a “forbidden” header name set by the browser, andAccept
is a CORS-safelisted header name, so you don’t need to include them inAccess-Control-Allow-Headers
Your request sends no
Content-Type
, so it isn’t needed inAccess-Control-Allow-Headers
in the response (and never needed forGET
requests and otherwise only needed if the type is other thanapplication/x-www-form-urlencoded
,text/plain
, ormultipart/form-data
)For
Access-Control-Allow-Methods
, your request seems to just be aGET
, so unless you plan to also makePOST
/PUT
/DELETE
/PATCH
requests, no point in explicitly including them