CORS与Symfony,jQuery,FOSRestBundle和NelmioCorsBundle

前端之家收集整理的这篇文章主要介绍了CORS与Symfony,jQuery,FOSRestBundle和NelmioCorsBundle前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠⚠TL;;;;;;;;:::::::::::::

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- *”头.

解决方法

其实我的设置很好.
绝对完美,如果我可以说.

这只是某种…愚蠢

出口被隐藏在一个PHP文件中.

对不起烦我想这是SO的一个文本/质量比例的记录.

编辑:我仍然希望这个问题可以成为完全CORS兼容的Symfony项目的一个正确例子.

原文链接:https://www.f2er.com/jquery/180520.html

猜你在找的jQuery相关文章