PhoneGap应用Chrome中AJAX请求遇405预请求错误求助
解决跨域预请求返回HTTP 405错误的问题
这个错误的核心原因是浏览器的CORS跨域预请求机制:当你发起的跨域请求属于「非简单请求」时,浏览器会自动先发送一个OPTIONS请求到目标服务器,用来验证服务器是否允许后续的实际请求(比如你的POST请求)。如果服务器没有正确处理这个OPTIONS请求,就会返回405 Method Not Allowed,导致实际请求被浏览器拦截。
结合你的代码来看,你的AJAX请求满足「非简单请求」的条件:
- 使用了
POST方法,并且设置了contentType: false、processData: false,这会让请求的Content-Type变为multipart/form-data(通常用于上传文件或复杂表单) - 自定义了
cache-control请求头
接下来给你几个具体的解决方向:
1. 服务器端必须正确处理OPTIONS请求
这是最关键的一步,因为预请求的控制权在服务器端。你需要在服务器的http://example.com/stack/api/order_food接口上,添加对OPTIONS方法的支持,返回以下响应头:
Access-Control-Allow-Origin: * # 或者指定你的前端域名,比如http://localhost:xxxx Access-Control-Allow-Methods: POST, OPTIONS Access-Control-Allow-Headers: cache-control, Content-Type Access-Control-Max-Age: 3600 # 可选,缓存预请求结果1小时,减少重复OPTIONS请求
并且确保OPTIONS请求的响应状态码是200或204,不能返回405。
不同后端语言的配置方式不同,举几个常见例子:
- Node.js/Express:可以用
cors中间件,配置允许的方法和请求头 - PHP:在接口开头添加header设置,并且判断请求方法为OPTIONS时直接返回200状态码
- Java Spring:配置CorsFilter或者在接口上添加
@CrossOrigin注解
2. 调整前端请求(如果不需要上传文件)
如果你的form数据只是普通的表单字段,不需要上传文件,那可以修改AJAX配置,让请求变成「简单请求」,从而避免预请求:
$.ajax({ "url": "http://example.com/stack/api/order_food", "type": "POST", "headers": { "cache-control": "no-cache" }, "processData": true, // 恢复默认,自动处理表单数据 "contentType": "application/x-www-form-urlencoded", // 表单默认的Content-Type "data": $(form).serialize(), // 序列化表单数据 success: function (resultData) { if(!resultData) { alert("Failed to get result data"); return; } var res = JSON.parse(resultData); if(res.status == "success") { alert("Success"); } else { alert("Failed"); } }, error: function (err) { console.log(err); } });
这样修改后,请求属于简单请求,浏览器不会发送OPTIONS预请求,也就不会触发405错误(前提是服务器已经允许跨域POST请求)。
3. 关于Content-Security-Policy的说明
你的CSP配置是没问题的,它只控制页面可以加载哪些资源,和跨域数据请求的CORS机制是两回事,所以不需要修改这部分。
内容的提问来源于stack exchange,提问作者V-Xtreme
相关产品推荐
相关产品推荐

