本文为转载文章,如果涉及侵权,请联系 suziwen1@gmail.com,会第一时间删除
Once in a while you need to make a cross-domain request from Javascript, this is something the browser very much dislikes. I’m no expert on CORS, and I feel that all the documentation on it is pretty bad. But I thought, “Anybody can google”, and so I did.
I started off with just adding the Access-Control-Allow-Origin header in my Apache configuration, thinking that it’ll solve my problems. I also decided to set it on wildcard, allowing anything to request resources.
- 1# In my virtualhost config
- 2Header set Access-Control-Allow-Origin "*"
Restart server, reload page, and I was greeted with the normal cross-domain error.
- 1# Chrome developer tools
- 2OPTIONS http://my.example.dev/setting/1316 405 (Method Not Allowed)
- 3
- 4# Firefox developer tools
- 5Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://my.example.dev/setting/1316\. This can be fixed by moving the resource to the same domain or enabling CORS.
I kept adding config flags until it looked something like this
- 1Header set Access-Control-Allow-Origin "*"
- 2Header set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
- 3Header set Access-Control-Max-Age "1000"
- 4Header set Access-Control-Allow-Headers "x-requested-with, Content-Type, origin, authorization, accept, client-security-token"
I still got the same error. At this point I started to look more into the error, “OPTIONS http://my.example.dev/setting/1316 405 (Method Not Allowed)” or “OPTIONS Method Not Allowed”, I looked under the network tab and noticed that the request method was “OPTIONS”, so I started digging and as if I understood correctly, this is a “pre-flight” request, basically asking the server for the CORS headers, but without data.
The API I was communicating with was not configured to handle OPTIONS request, nor was it supposed to. I decided I didn’t want to hack on the API code instead I wanted to try and circumvent this through Apache.
I added a small rewrite to the virtualhost configuration, basically responding with a 200 SUCCESS on every OPTIONS request.
- 1Header set Access-Control-Allow-Origin "*"
- 2Header set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
- 3Header set Access-Control-Max-Age "1000"
- 4Header set Access-Control-Allow-Headers "x-requested-with, Content-Type, origin, authorization, accept, client-security-token"
- 5
- 6# Added a rewrite to respond with a 200 SUCCESS on every OPTIONS request
- 7RewriteEngine On
- 8RewriteCond %{REQUEST_METHOD} OPTIONS
- 9RewriteRule ^(.*)$ $1
Progress! It still didn’t work, but I got a new error;
- 1# Chrome developer tools
- 2XMLHttpRequest cannot load http://my.example.dev/setting/1316\. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://mydevsite.dev' is therefore not allowed access.
- 3
- 4# Firefox developer tools
- 5Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://my.example.dev/setting/1316\. This can be fixed by moving the resource to the same domain or enabling CORS.
So by looking at the errors, it looks like the “Access-Control-Allow-Origin” response header is missing, but I’ve already added it to my config with a wildcard domain.
The problem occurs because I don’t cleanly respond with the RewriteRule, I actually redirect the request to a 200 SUCCESS which means earlier response flags were removed. All I had to do was set the “Always” flag on my “Header set” rule.
So for my final try, which was successful, my configuration looked like this;
- 1# Always set these headers.
- 2Header always set Access-Control-Allow-Origin "*"
- 3Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"
- 4Header always set Access-Control-Max-Age "1000"
- 5Header always set Access-Control-Allow-Headers "x-requested-with, Content-Type, origin, authorization, accept, client-security-token"
- 6
- 7# Added a rewrite to respond with a 200 SUCCESS on every OPTIONS request.
- 8RewriteEngine On
- 9RewriteCond %{REQUEST_METHOD} OPTIONS
- 10RewriteRule ^(.*)$ $1
And voilà, everything is playing nicely. Hopefully this can help another unfortunate soul trying to navigate through the pitfalls of CORS.
Please note that I haven’t used this config on a production server, just on local development servers, allowing wildcard domains for CORS will create security issues on your site!