There are lots of cases when we want to access the data from another domain using ajax, like in a.com
we want to access the apis deployed in api.a.com
, since the browser has the same-origin policy, we cannot send the ajax requests to api.a.com
.
We have some solutions to solve this problem:
- Using
jsonp
to send the requests, which has some other issues like security issue, we can only use theGET
method, - Using proxy in server side, like nginx, to delegate the requests to api.a.com, but we can only use a.com in browser side, which is still not so ideal,
- To solve the issues above, we can use CORS as a better solution.
How it works
Below is the basic cors flow:
The browser will check if the request is a cross origin ajax request, if yes, it will send a preflight request as http method OPTIONS
to server to get permissions, if the preflight response match the cross origin policies, then the browser will send the actual request to get real data.
There are couple headers you should notice in both request and response in preflight:
Access-Control-Request-Method
: Current request method, if the browser includes this header, the server should return theAccess-Control-Allow-Methods
with the value likeGET,POST
to tell the browser which method is allowed.Access-Control-Request-Headers
: the server should add theAccess-Control-Allow-Headers
with the value likeAccept, Content-Type
to the response headers to indicate all the headers that are allowed.- if the
withCredentials
property of the XMLHttpRequest object is set totrue
, the server should also respond theAccess-Control-Allow-Credentials: true
to the header. - And of course
Access-Control-Allow-Origin
is required for both the preflight and the actual request, the value could beAccess-Control-Allow-Origin: *
, which indicate that any site can access the data from the server, which is not so safe in real life production, so a better way to do is to set the value dynamically based on the request headerOrigin
, and your whitelist to see if the origin is allowed for the request. - The problem is that we don't want to send 2 requests every time we make cross origin request, which really costs a lot for the clients, especially for the mobile clients, to solve this, we can add
Access-Control-Max-Age
with the seconds you want the browser to cache the preflight.
After understand the basic of the CORS request, we can add this in our real express server.
Use CORS in Node Express App
-
First you may want to add a middleware to handle all the preflight requests:
app.use(function(req, res, next) { if ("OPTIONS" === req.method) { res.set("Access-Control-Allow-Origin", req.get("Origin")); res.set("Access-Control-Allow-Headers", "Accept, Content-Type"); //...add more if necessary res.end(); return; } next(); });
-
Actual request handler:
app.use(function(req, res, next) { //'Access-Control-Allow-Origin' is still required in actual response res.set("Access-Control-Allow-Origin", req.get("Origin")); res.json({}); });
Now you can access the apis from other domain without any restrictions, cheers :)