This issue is solved because I made a very stupid mistake in my code,not related to CORS or anything.
If you want to read this issue anyway,just note that it has a working CORS configuration,if you might want to take a good example.
⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️
(注释结尾)
情况
我有一个多域Symfony应用程序,后端部分由于某些原因更新数据与Web服务,而不是经典的形式.
后端:back.mydomain.dev
Web服务域:api.mydomain.dev
我正在使用jQuery对这些Web服务进行AJAX调用,如果我想修改或创建对象,我也发送AJAX请求,这些对象与Doctrine实体合并并持久化.
我一直在争取一年的GET,PUT,POST和DELETE请求,这个应用程序可以正常工作,只是因为它们在不同的域上,我被迫在不同的环境中设置CORS.
建立
所有jQuery AJAX请求如下所示:
ajaxObject = { url: 'http://api.mydomain.dev/' + uri,type: method,// Can be GET,POST or DELETE only dataType: 'json',xhrFields: { withCredentials: true },crossDomain: true,contentType: "application/json",jsonp: false,data: method === 'GET' ? data : JSON.stringify(data) // Here,"data" is ALWAYS containing a plain object. If empty,it equals to "{}" }; // ... Add callbacks depending on requests $.ajax(ajaxObject);
在后面,路线由Symfony管理.
对于CORS配置,我使用NelmioCorsBundle配置:
nelmio_cors: paths: "^/": allow_credentials: true origin_regex: true allow_origin: - "^(https?://)?(back|api)\.mydomain.dev/?" allow_headers: ['Origin','Accept','Content-Type'] allow_methods: ['POST','GET','DELETE','PUT','OPTIONS'] max_age: 3600 hosts: - "^(https?://)?(back|api)\.mydomain.dev/?"
使用的控件是扩展FOSRestBundle的,具有一些安全性(例如,当你没有正确的角色时,POST / PUT / DELETE不可能),可以更新对象并返回只有JSON数据(有一个监听器).
理想行为
理想情况下,我想要:
>运行jQuery AJAX POST / PUT / DELETE请求
>它必须向所有CORS头发送OPTIONS请求
> NelmioCorsBundle应该返回正确的CORS头,接受要完成的请求,即使在应用程序中运行任何控制器(由bundle的请求监听器创建)之前,
>如果接受,则将适当的HTTP请求作为序列化JSON字符串(在请求有效载荷中)发送到控制器,并且Symfony检索并将正确的JSON字符串解释为数组对象
>控制器然后获取数据,做它的东西,并返回一个应用程序/ json响应.
问题
但是在这里,我尝试过maaaaany组合,我似乎不能使它工作.
n°3和4点完全或部分失效.
试过解决办法
>当我不使用JSON.stringify序列化数据(见上面的安装部分)时,OPTIONS请求被发送,但是FOSRestBundle发送一个BadRequestHttpException,表示接收到无效的json消息,这是完全正常的,因为“请求负载”(as即使我在jQuery AJAX请求中指定了contentType:“application / json”,而应该是一个序列化的JSON字符串,这是经典的应用程序/ x-www-form-urlencoded内容.
>但是,如果我对数据var进行序列化,则“请求有效载荷”是有效的,但OPTIONS请求不发送,从而导致整个请求失败,因为缺少CORS验收.
>如果我用application / x-www-form-urlencoded或multipart / form-data替换contentType:“application / json”,并且不序列化数据,则请求有效载荷有效,但OPTIONS请求不是发送.它也应该是正常的,如in jQuery’s docs所述,在contentType参数下:
Note: For cross-domain requests,setting the content type to anything other than application/x-www-form-urlencoded,multipart/form-data,or text/plain will trigger the browser to send a preflight OPTIONS request to the server.
但是那么如何发送正确的CORS请求?
问题
>这个问题来自哪里?
这是我的设置问题吗?用jQuery?
> AJAX本身?
>什么可以解决这个死亡问题的不同解决方案?
编辑(评论后)
2015-06-29 17:39
条件:
在AJAX中,contentType设置为application / json.
数据选项设置为序列化的JSON字符串.
Preflight REQUEST标头
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/...
Preflight RESPONSE标头
HTTP/1.1 200 OK Access-Control-Allow-Credentials: true Access-Control-Allow-Methods: POST,GET,DELETE,OPTIONS Access-Control-Allow-Headers: origin,accept,content-type Access-Control-Max-Age: 3600 Access-Control-Allow-Origin: http://back.mydomain.dev
POST REQUEST标题(预检后)
POST http://api.mydomain.dev/fr/object/1 HTTP/1.1 Origin: http://back.mydomain.dev Content-Type: application/json Referer: http://back.mydomain.dev/... Cookie: mydomainPortal=v5gjedn8lsagt0uucrhshn7ck1 Accept: application/json,text/javascript,*/*; q=0.01
请求有效载荷(原始):
{ “JSON”:{ “ID”:1,“名称”: “对象”}}
必须注意的是,这会引发一个javascript错误:
XMLHttpRequest cannot load 07003. No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘07004’ is therefore not allowed access.
POST RESPONSE标头(预检后)
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
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"}');
然后,浏览器发送OPTIONS请求:
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,content-type Access-Control-Max-Age: 3600 Access-Control-Allow-Origin: http://back.mydomain.dev
但是,然后,浏览器发送POST请求,而没有任何“Access-Control- *”头.