CORS preflight request not handled by external API

2020-05-01 07:35发布

问题:

I'm trying to create front-end application for getresponse.com. It has own API which located at https://api.getresponse.com. When I'm trying to do any javascript request form browser with Axios or Fetch I've got this error:

Access to XMLHttpRequest at 'https://api.getresponse.com/v3/accounts' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

And in the network tab I have:

Request URL: https://api.getresponse.com/v3/accounts
Request Method: OPTIONS
Status Code: 400 Bad Request

So, as far as I can understand with API can't work with 'complex' requests from web browser properly.

Now I've got only one idea - to make some middleware, which will proxy my requests to API endpoints without any pre-flight requests.

Am I right? I can't find any examples of such a middleware. Where can I find any information?

回答1:

A CORS preflight request is a CORS request that checks to see if the CORS protocol is understood and a server is aware using specific methods and headers.

More details on the preflight request can be found here.

You should probably look into how to handle Content Security Policy on your server. For all the request you make from the javascript will be validated by the browser. So, your server should respond with the header Access-Control-Allow-Origin read more about the header here

By inspecting from browser network tab you should be able to view the headers which are present in your response.

As you do not have control on the API server, you can create a proxy server to communicate with the external servers. You can find a detailed tutorial here.

Here is an example nginx vhost configuration which handles a proxy for all requests with /api to https://api.example.com

server {
  listen 80;
  server_name example.com;   # Your server domain, in your case localhost
    location /api {
      access_log off;
      proxy_pass https://api.example.com;  # <--- this will the target domain
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

So, if you make http://example.com/api/v3/accounts, this will be forwarded to https://api.example.com/api/v3/accounts.

Basically you should have the below headers in your response.

Access-Control-Allow-Origin: https://yourdomain.com

You can also have below configuration.

Access-Control-Allow-Origin: *

If you use withCredentials then you cannot use the wildcard * for the Access-Control-Allow-Origin header, you should explicitly mention the domain.



回答2:

James answer is ok, but right now I'm more comfortable with solution based on Node.js rather than Nginx, as I developing locally on windows. I came up to the solutions with Express server:

var cors = require('cors')
var app = express()
var proxy = require('express-http-proxy'); 

app.use(cors())

app.use('/', proxy('https://api.getresponse.com'))

app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
})