发送application/json类型POST请求失败 文本请求正常的解决方案
问题原因
application/json 格式的跨域POST请求属于CORS规则定义的非简单请求,浏览器发起正式请求前会自动发送OPTIONS方法的预检请求,校验服务端是否允许当前跨域请求、是否支持对应的请求方法和请求头。
现有后端代码仅处理了GET和POST请求,没有对OPTIONS预检请求做响应,导致预检失败,浏览器直接拦截了正式POST请求。
这也是text/plain、application/x-www-form-urlencoded格式的请求可以正常发送的原因——这两类Content-Type的POST请求属于简单请求,不会触发预检流程;不受浏览器CORS规则限制的接口测试工具,自然也不会有预检拦截的问题。
修复方法
修改服务端Cloudflare Workers代码
补充OPTIONS预检请求的处理逻辑,返回完整的CORS响应头,允许携带Content-Type头的跨域POST请求,修改后完整代码如下:
addEventListener('fetch', event => { event.respondWith(handleRequest(event.request)); }); async function handleRequest(request) { // 统一配置CORS响应头 const commonHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type', 'content-type': 'text/plain' }; // 单独处理OPTIONS预检请求 if (request.method === 'OPTIONS') { return new Response(null, { status: 204, headers: commonHeaders }); } if (request.method === 'GET') { return new Response('Hello Worker!', { headers: commonHeaders }); } else if (request.method === 'POST') { return new Response('Response for POST!', { headers: commonHeaders }); } else { return new Response('Expected POST', { status: 500, headers: commonHeaders }); } }
前端代码无需调整
现有前端通过Fetch发送JSON格式POST请求的逻辑没有问题,服务端修改部署完成后即可正常发起请求。
补充说明:浏览器判定跨域简单请求的核心条件为:请求方法属于GET/POST/HEAD三者之一,且Content-Type取值仅限
application/x-www-form-urlencoded、multipart/form-data、text/plain,不满足条件的跨域请求都会触发OPTIONS预检流程。
内容的提问来源于stack exchange,提问作者Dashu
相关产品推荐
相关产品推荐

