简体   繁体   中英

CORS header ‘Access-Control-Allow-Origin’ missing when making a request to different port on localhost

I have a node web server (express) running on port 6000 .

When http://localhost:6000/ is invoked, index.html is served to the client which has a script, logic.js that runs:

var xhr = new XMLHttpRequest();
var url = 'http://localhost:4000/endpoint';
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-type', 'application/json');
xhr.onreadystatechange = function() {
  if (xhr.readyState === 4 && xhr.status === 200) {
    console.log('endpoint');
    callback(xhr.responseText);
  }
};
xhr.send(JSON.stringify({'key': 'value'}));

There is another express server running on port 4000 .

The server sets up an endpoint which simply returns what the request body submitted:

app.route('/segment')
  .post(bodyParser.json(), function(req, res) {
  res.set('Access-Control-Allow-Origin', '*');
  res.send(req.body);
});

When I access http://localhost:6000/ , I'm seeing this in the browser console:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:4100/segment. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing)

Is there a way to bypass this during prototyping?

Your endpoint probably doesn't serve the OPTIONS HTTP method which is used by browsers to check CORS headers (before they make the real request).

If you need different CORS headers in development and in production, I think the best way is to add a new backend config option with the value for allowed origins and serve them from some global response filter.

You have set xhr.setRequestHeader('Content-type', 'application/json'); so this is a preflighted request (rule of thumb: A Content-Type that is not a valid value for the enctype attribute of an HTML form will trigger a preflighted request).

Your server side code only sets the Access-Control-Allow-Origin header in response to POST requests. You need to write server side code to respond to the preflight OPTIONS request too.

Here are a few ways to solve this problem:

Best: CORS header (requires server changes)

CORS (Cross-Origin Resource Sharing) is a way for the server to say “I will accept your request, even though you came from a different origin.” This requires cooperation from the server – so if you can't modify the server (eg if you're using an external API), this approach won't work.

Modify the server to add the header Access-Control-Allow-Origin: * to enable cross-origin requests from anywhere (or specify a domain instead of *). This should solve your problem.

2nd choice: Proxy Server

If you can't modify the server, you can run your own proxy. And this proxy can return the Access-Control-Allow-Origin header if it's not at the Same Origin as your page.

Instead of sending API requests to some remote server, you'll make requests to your proxy, which will forward them to the remote server. Here are a few proxy options.

3rd choice: JSONP (requires server support)

If CORS and the proxy server don't work for you, JSONP may help. You essentially make a GET request with a callback parameter:

(get) http://api.example.com/endpoint?callback=foo The server will wrap the JSON reply in a function call to your callback, where you can handle it:

foo({"your": "json", here: true}) There are some downsides, notably that JSONP only supports GET requests and that you still need a cooperative server.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM