javascript POST 到外部 API 会抛出 CORS,但它可以从 Postman 工作

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/53684484/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 10:16:44  来源:igfitidea点击:

POSTing to external API throws CORS but it works from Postman

javascriptnode.jscorsimgurnode-fetch

提问by Cristian G

I am using the imgur api to upload imagesvia a node js app.

我正在使用 i mgur api通过节点 js 应用程序上传图像

I am converting images to base64 strings and sending them via Postman works great.

我正在将图像转换为 base64 字符串并通过 Postman 发送它们效果很好。

I use node-fetchto make api calls.

node-fetch用来进行api调用。

const fetch = require('node-fetch')
...
async uploadImage(base64image) {
        try {
            const url = 'https://api.imgur.com/3/image'
            const res = await fetch(url,
                {
                    method: 'POST',
                    body: { image: base64image },
                    headers: {
                        'content-type': 'application/json',
                        'Authorization': 'Client-ID [my-client-id]',
                        'Access-Control-Allow-Headers': 'Content-Type, Authorization, Access-Control-Allow-Headers',
                        'Access-Control-Allow-Methods': 'POST',
                    }
                }
            )

            console.log(res)
        } catch(err) {
            console.log(err)
        }
    }

Error: Access to fetch at 'https://api.imgur.com/3/image' from origin 'http://localhost:3000' has been blocked by CORS policy: Request header field Access-Control-Allow-Headersis not allowed by Access-Control-Allow-Headersin preflight response.

错误:从源“ http://localhost:3000”获取“ https://api.imgur.com/3/image”的访问已被 CORS 策略阻止:请求标头字段Access-Control-Allow-Headers为预检响应中的Access-Control-Allow-Headers 不允许

I have tried many 'Access-Control-Allow-xxx' headers but none of them worked..

我试过很多“Access-Control-Allow-xxx”头文件,但都没有奏效。

I assume it must be something simple that I am missing. I have been stuck on this for hours please help me.

我认为它一定是我遗漏的一些简单的东西。我已经坚持了几个小时,请帮助我。

回答by Aritra Chakraborty

That's because Access-Control-Allow-Headers, Access-Control-Allow-Methodsare the headers that is used by the server. The server appends the header by a middleware.

那是因为Access-Control-Allow-Headers,Access-Control-Allow-Methods是服务器使用的标头。服务器通过中间件附加标头。

Now, imagine in the server(in this below example an express server) with CORS enabled this kind of (default) headers are getting set:

现在,想象在启用了 CORS 的服务器(在下面的示例中是一个快速服务器)中,正在设置这种(默认)标头:

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, Accept');
});

And you are sending Access-Control-Allow-Headersfrom the client side, and server sees that as a header that is not whitelisted.

Access-Control-Allow-Headers从客户端发送,服务器将其视为未列入白名单的标头。

So, in headers just use these:

因此,在标题中只需使用这些:

headers: {
    'content-type': 'application/json',
    'Authorization': 'Client-ID [my-client-id]'
}

It should work fine.

它应该可以正常工作。

Btw, I think it is working with postman because:

顺便说一句,我认为它正在与邮递员合作,因为:

  • Postman cannot set certain headers if you don't install that tiny postman capture extension.
  • Browser security stops the cross origin requests. If you disable the chrome security it will do any CORS request just fine.
  • 如果您不安装那个微小的邮递员捕获扩展程序,邮递员将无法设置某些标题。
  • 浏览器安全停止跨源请求。如果您禁用 chrome 安全性,它会很好地执行任何 CORS 请求。

Also, according to this:

另外,根据这个

I believe this might likely be that Chrome does not support localhostto go through the Access-Control-Allow-Origin-- see Chrome issue

To have Chrome send Access-Control-Allow-Originin the header, just alias your localhost in your /etc/hosts file to some other domain, like:

127.0.0.1   localhost yourdomain.com

Then if you'd access your script using yourdomain.cominstead of localhost, the call should succeed.

我相信这可能是 Chrome 不支持 localhost通过Access-Control-Allow-Origin--参见 Chrome 问题

要让 Chrome 发送Access-Control-Allow-Origin标头,只需将 /etc/hosts 文件中的 localhost 别名为其他域,例如:

127.0.0.1   localhost yourdomain.com

然后,如果您使用yourdomain.com而不是 访问您的脚本localhost,则调用应该会成功。

Note: I don't think the content type should be application/jsonit should be like image/jpegor something. Or maybe don't include that header if it doesn't work.

注意:我认为内容类型不应该是application/json它应该像image/jpeg什么的。或者,如果它不起作用,也许不要包含该标题。

回答by Jatin Gupta

Browser restricts HTTP requests to be at the same domain as your web page, so you won't be able to hit imgur api directly from the browser without running into CORS issue.

浏览器将 HTTP 请求限制在与您的网页相同的域中,因此您将无法直接从浏览器点击 imgur api 而不会遇到 CORS 问题。

I am converting images to base64 strings and sending them via Postman works great.

我正在将图像转换为 base64 字符串并通过 Postman 发送它们效果很好。

That's because Postman is not a browser, so is not limited by CORS policy.

这是因为 Postman 不是浏览器,因此不受 CORS 策略的限制。

I have tried many 'Access-Control-Allow-xxx' headers but none of them worked..

我试过很多“Access-Control-Allow-xxx”头文件,但都没有奏效。

These headers must be returned by the server in response - in your case by the imgur server. You can't set them in the request from browser, so it'll never work.

这些标头必须由服务器作为响应返回 - 在您的情况下由 imgur 服务器返回。你不能在浏览器的请求中设置它们,所以它永远不会工作。

Error: Access to fetch at 'https://api.imgur.com/3/image' from origin 'http://localhost:3000' has been blocked by CORS policy: Request header field Access-Control-Allow-Headers is not allowed by Access-Control-Allow-Headers in preflight response.

错误:从源“ http://localhost:3000”获取“ https://api.imgur.com/3/image”的访问已被 CORS 策略阻止:请求标头字段 Access-Control-Allow-Headers 为预检响应中的 Access-Control-Allow-Headers 不允许。

Possible solutions to your problem:

您的问题的可能解决方案:

  1. If you have access to the backend api you can set the "Access-Control-Allow-Origin" header on the server and let your app access the api - but as you won't have access to the imgur server - you probably can't do that.

  2. Disable CORS in the browser - you can use a plugin like: https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en. This workaound should be fine for development. The plugin will disable your CORS settings and you will be able to hit imgur apis.

  3. The third solution is using a proxy. You can setup a small node server using express. You will then hit your own node server, which in turn will hit the imgur api. As node server is not a browser environment, it won't have any CORS issue and you will be able to access imgur API that way. This is also the reason you were able to hit the API from Postman without any issues. As Postman is not a browser environment, it's not limited by CORS policy.

  1. 如果您有权访问后端 api,则可以在服务器上设置“Access-Control-Allow-Origin”标头并让您的应用程序访问 api - 但由于您无法访问 imgur 服务器 - 您可能可以'不要那样做。

  2. 在浏览器中禁用 CORS - 您可以使用如下插件:https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en。这种解决方法应该适合开发。该插件将禁用您的 CORS 设置,您将能够点击 imgur api。

  3. 第三种解决方案是使用代理。您可以使用 express 设置一个小型节点服务器。然后,您将访问您自己的节点服务器,该服务器又将访问 imgur api。由于节点服务器不是浏览器环境,它不会有任何 CORS 问题,您将能够通过这种方式访问​​ imgur API。这也是您能够毫无问题地从 Postman 访问 API 的原因。由于 Postman 不是浏览器环境,因此不受 CORS 策略的限制。