在使用Axios / http请求设置标头时,我在向服务器发出请求时遇到问题。我添加的任何标头(content-type
标头除外)都会导致相同的错误:"预检的响应具有无效的HTTP状态代码405。"这在Chrome,Firefox,Edge等中都是如此。
具体来说,我需要为我需要连接的服务添加Authorization标头以进行帐户验证。
使用API URI在Postman上运行GET请求工作正常,我得到了所需的响应。在浏览器中的React应用程序中运行它会给出HTTP 405错误。我在安装了Google Allow-Control-Origin
扩展程序的本地节点服务器上运行此操作,并使用http://localhost:3000
启用。
当我运行没有任何标头参数的请求时:
axios.get("https://myrequest.com/req/reqservice.svc/Login",).then(data => console.log(data)).catch(err => console.log(err))
请求正常。当我使用标题(任何标题,但在我的情况下,授权标题)运行它时,我收到错误:
axios.get("https://myrequest.com/req/reqservice.svc/Login", { headers: { "Authorization": "randomExample" } }).then(data => console.log(data)).catch(err => console.log(err))
那么,可能导致这个问题的原因是什么?如果是CORS或连接问题,我一般无法提出请求吗?我一直在仔细阅读Stack Overflow而没有回答给我解决方案。我完全迷失了该做什么,而且我已经在没有一个解决方案的情况下工作了好几天。任何意见都会非常感激。
答案 0 :(得分:8)
归功于CORS。您需要为预检(OPTIONS)请求(Documentation)Access-Control-Allow-Headers
服务器端指定正确的值
More details about CORS in general
修改您的服务器以添加缺少的标头。根据您的问题,您至少需要添加Authorization
值。
节点js服务器
app.use(function (req, res, next) {
//...
res.setHeader('Access-Control-Allow-Headers', 'Authorization');
关于访问控制允许标题
Access-Control-Allow-Headers响应标头用于响应预检请求,以指示在实际请求期间可以使用哪些HTTP标头。
因此,在服务器端响应中,设置Access-Control-Allow-Headers
时,您需要指定以逗号分隔标题的列表。
Access-Control-Allow-Headers: <header-name>, <header-name>, ...
您只需为自定义标头指定它,因为默认情况下已接受一些标头。
简单标题,接受,接受语言,内容语言,内容类型(但只有其应用程序/ x-www-form-urlencoded,multipart / form的解析值的MIME类型(忽略参数) -data或text / plain)始终可用,并且不需要通过此标题列出。
因此,在您的情况下,如果您只指定Content-type
,则可以使用,因为默认情况下会接受Content-Type
(如上所述)
注意如果Content-type
的值不属于上述类型之一(例如,如果您将授权请求提交为application/json
),则需要添加它在列表中(逗号分隔)
节点js服务器
app.use(function (req, res, next) {
//...
res.setHeader('Access-Control-Allow-Headers', 'Authorization, Content-Type');
答案 1 :(得分:2)
如果您想要启用所有路线,请将以下脚本添加到index.js
。
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
如果您只想启用单个路由器,则可以启用它:
router.get('/corspage', function(req, res) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', true);
res.send('cors problem fixed:)');
});
如果您可以使用其他软件包,则可以使用cors软件包来完成更少的代码。安装软件包并将以下代码添加到index.js
。
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
app.get('/products/:id', function (req, res, next) {
res.json({msg: 'This is CORS-enabled for all origins!'})
})
如果您想使用 cors 包启用单一路线:
var express = require('express')
var cors = require('cors')
var app = express()
app.get('/products/:id', cors(), function (req, res, next) {
res.json({msg: 'This is CORS-enabled for a Single Route'})
})
答案 2 :(得分:0)
发生此错误是因为这是一个CORS调用,并且您收到了服务器必须相应响应的预检请求:
您将从客户端获得Origin: http://blah.com
标头。
在回复预检检查时,您应该设置几个标题:
Access-Control-Allow-Origin: http://blah.com
- 为所有来源设置允许的来源* - 如果需要,则设置域名
Access-Control-Allow-Credentials: true
- 设置是否允许来自此来源的Cookie。
Access-Control-Allow-Methods: POST, GET, OPTIONS
- 此来源允许的行为。
Access-Control-Allow-Headers: Content-Type
- 此来源允许哪些标头,您可以在此设置自定义标头。
这些预检检查是OPTIONS调用而非GET或POST,因此您可以轻松检测并正确回答。您可能无法回答选项调用的内容,但只设置这些必需的标头,以便客户端知道此连接的CORS策略是什么。完成此操作后,客户端将发出实际的GET / POST请求,因为您已在调用服务器的ajax中发出它。