Ale*_*ock 20 ajax jquery cors symfony fosrestbundle
这个问题解决了,因为我在我的代码中犯了一个非常愚蠢的错误,与CORS或任何东西无关.
如果你想要阅读这个问题,请注意它有一个有效的CORS配置,如果你想要一个很好的例子.
(注意结束)
我有一个多域Symfony应用程序,后端部分由于某些原因使用Web服务而不是经典表单更新数据.
后端:back.mydomain.dev Webservices域: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, PUT, 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);
Run Code Online (Sandbox Code Playgroud)
在后面,路线由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/?"
Run Code Online (Sandbox Code Playgroud)
使用的控制器是扩展FOSRestBundle的一个,有一些安全性(例如,当你没有正确的角色时不能POST/PUT/DELETE),可以更新对象并只返回JSON数据(有一个监听器) .
理想情况下,我想要这个:
application/json
响应.但在这里,我尝试了maaaaany组合,我似乎无法使它工作.
点n°3和4点完全或部分失效.
当我没有序列化data
with时JSON.stringify
(参见上面的Setup部分),OPTIONS请求被发送,但是FOSRestBundle发送了一个BadRequestHttpException
说法Invalid json message received
,这是完全正常的,因为"请求有效载荷"(如Chrome的开发者工具中所见)是经典application/x-www-form-urlencoded
内容即使我contentType: "application/json"
在jQuery AJAX请求中指定,它应该是一个序列化的JSON字符串.
但是,如果我对var 进行序列化data
,则"请求有效负载"有效,但OPTIONS请求不会发送,因为缺少CORS接受而导致整个请求失败.
如果我contentType: "application/json"
用application/x-www-form-urlencoded
或替换multipart/form-data
,并且不对数据进行序列化,则请求有效负载有效,但不发送OPTIONS请求.它也应该是正常的,正如jQuery在contentType参数下的文档中所解释的那样:
注意:对于跨域请求,将内容类型设置为application/x-www-form-urlencoded,multipart/form-data或text/plain以外的任何内容将触发浏览器向服务器发送预检OPTIONS请求.
但是,如何发送正确的CORS请求?
2015-06-29 17:39
在AJAX中,contentType
设置为application/json
.该data
选项设置为序列化的JSON字符串.
预检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/...
Run Code Online (Sandbox Code Playgroud)
预检RESPONSE标头
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
请求有效负载(原始):
{"json":{"id":1,"name":"object"}}
必须注意,这会抛出一个javascript错误:
XMLHttpRequest无法加载http://api.mydomain.dev/fr/object/1.请求的资源上不存在"Access-Control-Allow-Origin"标头.因此,不允许来源' http://back.mydomain.dev '访问.
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
Run Code Online (Sandbox Code Playgroud)
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"}');
Run Code Online (Sandbox Code Playgroud)
然后,浏览器发送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
Run Code Online (Sandbox Code Playgroud)
返回正确的响应标头:
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
Run Code Online (Sandbox Code Playgroud)
但是,浏览器发送POST请求时没有任何"Access-Control-*"标头.
Ale*_*ock 13
实际上,我的设置运作良好.
如果我可以说的话,绝对完美.
这只是某种......愚蠢.
一个exit;
隐藏在PHP文件的深处.
对不起烦恼.我想这是SO上文本/质量比的记录.
编辑:我仍然希望这个问题可以成为完全兼容CORS的Symfony项目的正确例子.
归档时间: |
|
查看次数: |
8220 次 |
最近记录: |