带有Symfony、jQuery、FOSRestBundle和NelmioCorsBundle的CORS ⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️TL;博士:编辑(在阅读全文之前):
这个问题已解决,因为我在代码中犯了一个非常愚蠢的错误,与CORS或其他任何东西无关。带有Symfony、jQuery、FOSRestBundle和NelmioCorsBundle的CORS ⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️TL;博士:编辑(在阅读全文之前):,jquery,ajax,symfony,cors,fosrestbundle,Jquery,Ajax,Symfony,Cors,Fosrestbundle,这个问题已解决,因为我在代码中犯了一个非常愚蠢的错误,与CORS或其他任何东西无关。 如果您想阅读本期文章,请注意,如果您想举个好例子,它有一个工作CORS配置 ⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️ (注完) 处境 我有一个多域Symfony应用程序,由于某些原因,后端部分使用web服务而不是经典表单更新数据 后端:Back.mydomain.dev Webservices域:api.mydomain.dev 我使用jQuery对这些web服务进行AJAX调用,如果我想修改或创建对象
如果您想阅读本期文章,请注意,如果您想举个好例子,它有一个工作CORS配置 ⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️ (注完) 处境 我有一个多域Symfony应用程序,由于某些原因,后端部分使用web服务而不是经典表单更新数据 后端:Back.mydomain.dev Webservices域:api.mydomain.dev 我使用jQuery对这些web服务进行AJAX调用,如果我想修改或创建对象,我也会发送AJAX请求,这些对象会与doctor实体合并并持久化 我花了整整一年的时间来努力提出GET、PUT、POST和DELETE请求,这些请求可以在这个应用程序上正常工作,仅仅因为它们位于不同的域,我就不得不在不同的环境中设置CORS 安装程序 所有jQuery AJAX请求如下所示:
ajaxObject={
网址:'http://api.mydomain.dev/"乌里,,
type:method,//只能是GET、PUT、POST或DELETE
数据类型:“json”,
xhrFields:{
证书:正确
},
跨域:是的,
contentType:“应用程序/json”,
jsonp:false,
data:method==“GET”?data:JSON.stringify(data)//这里,“data”总是包含一个普通对象。如果为空,则它等于“{}”
};
// ... 根据请求添加回调
$.ajax(ajaxObject);
后面的路线由Symfony管理
对于CORS配置,我将使用以下配置:
nelmio_cors:
路径:
"^/":
允许\u凭据:true
来源(regex):对
允许来源:
-“^(https?:/)?(back | api)\.mydomain.dev/?”
允许_头:['Origin','Accept','Content-Type']
允许使用方法:['POST'、'GET'、'DELETE'、'PUT'、'OPTIONS']
最高年龄:3600
主持人:
-“^(https?:/)?(back | api)\.mydomain.dev/?”
所使用的控制器是扩展的,具有一定的安全性(例如,当您没有正确的角色时,无法POST/PUT/DELETE),可以更新对象并仅返回JSON数据(有一个侦听器)
理想行为
理想情况下,我希望:
application/json
响应JSON.stringify
序列化数据时(请参阅上面的设置部分),会发送选项请求,但FOSRestBundle会发送一个BadRequestHttpException
表示收到了无效的JSON消息,这是完全正常的,因为“请求有效负载”(在Chrome的开发者工具中可以看到)是经典的application/x-www-form-urlencoded
内容,即使我在jQuery AJAX请求中指定了contentType:“application/json”
,但它应该是一个序列化的json字符串
数据
var,“请求有效负载”是有效的,但是选项请求没有发送,使得整个请求由于缺少CORS接受而失败contentType:“application/json”
使用应用程序/x-www-form-urlencoded
或多部分/表单数据
,并且不序列化数据,则请求有效负载有效,但不会发送选项请求。这也应该是正常的,如contentType参数下所述:
注意:对于跨域请求,将内容类型设置为除application/x-www-form-urlencoded、multipart/form data或text/plain之外的任何内容,都会触发浏览器向服务器发送飞行前选项请求
但是,如何发送正确的CORS请求呢- 这个问题从何而来
- 我的设置有问题吗?jQuery有问题吗
- 使用AJAX本身
- 有什么不同的解决方案可以解决这个该死的问题
contentType
设置为application/json
。
data
选项设置为序列化JSON字符串
飞行前请求头
OPTIONS http://api.mydomain.dev/fr/object/1 HTTP/1.1
Access-Control-Request-Method: POST
Origin: http://back.mydomain.dev
Access-Control-Request-Headers: accept, content-type
Referer: http://back.mydomain.dev/...
飞行前响应头
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: POST, GET, DELETE, PUT, OPTIONS
Access-Control-Allow-Headers: origin, accept, content-type
Access-Control-Max-Age: 3600
Access-Control-Allow-Origin: http://back.mydomain.dev
POST
请求标头(飞行前之后)
请求有效负载(原始):
{“json”:{“id”:1,“name”:“object”}
必须注意,这会引发javascript错误:
无法加载XMLHttpRequest。请求的资源上不存在“Access Control Allow Origin”标头。因此不允许访问源“”
POST
响应标题(飞行前)
2015-06-29 17:39 我还尝试使用vanilla javascript生成XMLHttpRequest,问题仍然是一样的:
var xhr = new XMLHttpRequest;
xhr.open('POST', 'http://api.mydomain.dev/fr/objects/1', true);
xhr.setRequestHeader('Content-type', 'application/json');
xhr.withCredentials = true; // Sends cookie
xhr.onreadystatechange = function(e) {
// A simple callback
console.info(JSON.parse(e.target.response));
};
// Now send the request with the serialized payload:
xhr.send('{"id":1,"name":"Updated test object"}');
然后,眉毛
HTTP/1.1 200 OK
Date: Mon, 29 Jun 2015 15:35:07 GMT
Server: Apache/2.4.12 (Unix) OpenSSL/1.0.2c Phusion_Passenger/5.0.11
Keep-Alive: timeout=5, max=91
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8
var xhr = new XMLHttpRequest;
xhr.open('POST', 'http://api.mydomain.dev/fr/objects/1', true);
xhr.setRequestHeader('Content-type', 'application/json');
xhr.withCredentials = true; // Sends cookie
xhr.onreadystatechange = function(e) {
// A simple callback
console.info(JSON.parse(e.target.response));
};
// Now send the request with the serialized payload:
xhr.send('{"id":1,"name":"Updated test object"}');
OPTIONS http://api.mydomain.dev/fr/objects/1 HTTP/1.1
Connection: keep-alive
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: POST
Origin: http://back.mydomain.dev
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: POST, GET, DELETE, PUT, OPTIONS
Access-Control-Allow-Headers: origin, accept, content-type
Access-Control-Max-Age: 3600
Access-Control-Allow-Origin: http://back.mydomain.dev