浏览器与服务器端均遭遇CORS验证失败问题求助
CORS问题排查与解决方案
问题场景
客户端页面部署在localhost:3000,通过fetch向localhost:3001发送POST请求时,浏览器触发了预检OPTIONS请求,最终返回CORS报错。
客户端代码(index.html)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <link rel="icon" href="/favicon.ico"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script> async function post() { const res = await fetch('http://localhost:3001', { method: 'POST', body: '{"msg":1}', headers: { 'Access-Control-Allow-Origin': 'http://localhost:3000', 'Content-Type': 'text/plain' }, mode: 'cors' }) console.log(await res.text()) } </script> </head> <body> <button onclick="post()">POST</button> </body> </html>
服务端代码(server.js,基于Express)
// server.js using express import express from 'express' const server = express() server.options('*', (req, res) => { res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000') // 小写设置同样无效 res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS') res.setHeader('Access-Control-Allow-Credentials', 'true') res.setHeader('Access-Control-Allow-Headers', 'Content-Type') res.send(); }) server.post('/', (req, res) => { console.log('POST /') res.send('OK') }) server.listen(3001, () => { console.log('listening') })
报错信息
Access to fetch at 'http://localhost:3001/' from origin 'http://localhost:3000' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response.
Wireshark捕获的请求信息

问题原因
- 非法请求头设置:
Access-Control-Allow-Origin是服务端返回给客户端的响应头,不属于客户端请求时该携带的头。客户端额外添加这个头后,服务端预检响应的Access-Control-Allow-Headers未包含该字段,触发报错。 - 原本
Content-Type: text/plain属于简单请求范畴,但因添加了非法请求头,浏览器自动触发预检OPTIONS请求。
解决方案
1. 修正客户端请求头
移除fetch配置中多余的Access-Control-Allow-Origin头,修改后客户端脚本如下:
<script> async function post() { const res = await fetch('http://localhost:3001', { method: 'POST', body: '{"msg":1}', headers: { 'Content-Type': 'text/plain' }, mode: 'cors' }) console.log(await res.text()) } </script>
2. 优化服务端配置
当前场景下原有服务端配置已满足需求,若后续需添加自定义请求头,需确保Access-Control-Allow-Headers包含对应字段。建议在POST接口中也返回Access-Control-Allow-Origin头,避免潜在问题:
server.post('/', (req, res) => { console.log('POST /') res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000') res.send('OK') })
内容的提问来源于stack exchange,提问作者Jackoo
相关产品推荐
相关产品推荐

