date: 2018-11-04
tags: Web
First of all, it is very important that CORS error is a restriction from browser. And when a server is sending some request to other server, no CORS error will happens. Therefore, we can use our server (the code we can modify and control) as a medium to connect frontend and some resource from other resources. And the following codes are all for our intermediate server.
There are mainly two kinds for CORS. CORS for simple request and CORS for preflight request.
Simple request is GET request or POST request with Content-Type in one of application/x-www-form-urlencoded, multipart/form-data, text/plain. Note that the commonly used application/json is not simple request. Those Content-Type are exceptions due to historical legacy.
For simple request we only need to add an Origin: http://api.bob.com
in the request header.
GET /cors HTTP/1.1 Origin: http://api.bob.com Host: api.alice.com Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0...
And add Access-Control-Allow-Origin: http://api.bob.com
in the response.
Access-Control-Allow-Origin: http://api.bob.com Access-Control-Allow-Credentials: true Access-Control-Expose-Headers: FooBar Content-Type: text/html; charset=utf-8
Or simply use Access-Control-Allow-Origin: *
in the response.
If hoping to add cookie to the request, we need to add "withCredentials: true" in the request and "Access-Control-Allow-Credentials: true" in the server. Note that when sending cookie, we cannot set "Access-Control-Allow-Origin" as "*", but the domain of client.
For request other than simple request, the client will add another request as preflight request. Only when the domain of client is in the allowed list of server, the client will then send the original request to the server.
The preflight request will look like this:
OPTIONS /cors HTTP/1.1 Origin: http://api.bob.com Access-Control-Request-Method: PUT Access-Control-Request-Headers: X-Custom-Header Host: api.alice.com Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0...
And the server will need to return status code 200 for this request. Here is an express middleware that can solve this problem nicely,
// add header and return for OPTIONS request
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
//intercepts OPTIONS method
if ('OPTIONS' === req.method) {
//respond with 200
res.send(200);
}
else {
//move on
next();
}
});