【Node.js】请求的资源没有设置 ‘Access-Control-Allow-Origin’ 头。Explanation: 【Node.js】请求的资源没有设置 ‘Access-Control-Allow-Origin’ 头
你好,我是拉斯卡尔,辛苦了。
我在工作中负责后端和前端,当我尝试使用Graphql连接两者的实现时,遇到了以下错误。
Access to XMLHttpRequest at 'http://localhost:4000/graphql'
from origin 'http://localhost:3000' 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.
嗯,看起来后端根据前端请求遵循某种名为CORS的规约,可能是在暗示「嘿,请求必须遵守规则并发送过来?」,表现出了一种生气的样子?。
情况说明
后端
我們使用Node.js中的Express框架以及TypeScript來實現後端功能。
我們與我們自家的AWS建立了連接,可以根據請求返回圖像和數據等。
我們的實現使用GraphQL來接收請求,並且在本地環境中也確認了正確返回預期響應的功能。
在这个时候,端口号为4000,也就是说localhost:4000/graphql是后端的URI。
前端。
前端使用React和TypeScript来实现,首次加载时使用GraphQL向后端发出请求,并显示接收到的响应内容,这是一个非常简单的实现。
在这个时候,端口是3000,也就是说localhost:3000/是前端的URI。
错误的原因
错误信息已经写在了上面,要说的就是因为使用了CORS禁止的请求方式,所以才会出现错误。
暂且不谈CORS的细节,简单总结一下,不允许接受来自不同域名的请求,这是通过浏览器规定的。
确实
-
- フロントエンドはlocalhost:3000/
- バックエンドはlocalhost:4000/
由于与不同的域名不一样,所以遇到了CORS的问题。
嗯,如果仔细考虑的话,可以从不同的域名访问可能在安全方面不太理想。
谢谢,CORS?
解决方案
开头的话说得有点长了。
总结起来,只需要安装一个名为”cors”的node模块就能解决问题了。
npm install --save cors
此外,如果您正在使用TypeScript。
npm install --save-dev @types/cors
让我们先安装好。
完成后,我们将开始进行后端实现。
实现只需添加app.use(cors ())即可。
const app = express()
++ app.use(cors())
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true
}))
app.listen(4000, () => {
console.log('Start Express GraphQL Server. Listen to localhost:4000/graphql')
});
我认为通过以上方法可以解决错误。
只要从特定的域名接收请求,就会搭建一个可以从任何域名访问的系统。(虽然是本地主机,所以应该没有太大的影响,但为了以后考虑,)我们会实现仅接受来自特定域名的请求。
const app = express()
++ const corsOptions = {
origin: 'http://localhost:3000',
optionsSuccessStatus: 200
}
++ app.use(cors(corsOptions))
-- app.use(cors())
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true
}))
app.listen(4000, () => {
console.log('Start Express GraphQL Server. Listen to localhost:4000/graphql')
});
创建一个名为corsOptions的变量,该变量包含允许的域和成功后的状态码。将该变量作为cors()的参数传递即可?。
额外内容:未能解决的处理方法
在研究CORS相关内容时,发现可以不必特意安装CORS模块,
const app = express()
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true
}))
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin', 'http://localhost:3000');
res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
res.header('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS');
res.header('Access-Control-Max-Age', '86400');
next();
});
app.listen(4000, () => {
console.log('Start Express GraphQL Server. Listen to localhost:4000/graphql')
});
我在许多地方看到了类似的建议,说只要覆盖标头就可以了,但在我的环境中并没有成功。我会继续研究,等我弄清楚后再补充说明。?