在下面的代码中,AngularJS $http方法调用URL,并提交xsrf对象作为“Request Payload”(在Chrome调试器网络选项卡中描述)。jQuery $。ajax方法做同样的调用,但提交xsrf作为“表单数据”。
如何让AngularJS将xsrf作为表单数据而不是请求有效载荷提交?
var url = 'http://somewhere.com/';
var xsrf = {fkey: 'xsrf key'};
$http({
method: 'POST',
url: url,
data: xsrf
}).success(function () {});
$.ajax({
type: 'POST',
url: url,
data: xsrf,
dataType: 'json',
success: function() {}
});
从AngularJS v1.4.0开始,就有一个内置的$httpParamSerializer服务,它可以根据文档页面上列出的规则将任何对象转换为HTTP请求的一部分。
它可以这样使用:
$http.post('http://example.com', $httpParamSerializer(formDataObj)).
success(function(data){/* response status 200-299 */}).
error(function(data){/* response status 400-999 */});
请记住,对于正确的表单post, Content-Type头必须更改。要对所有POST请求全局执行此操作,可以使用以下代码(取自Albireo的half-answer):
$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
为了只针对当前post,需要修改request-object的headers属性:
var req = {
method: 'POST',
url: 'http://example.com',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: $httpParamSerializer(formDataObj)
};
$http(req);
AngularJS的做法是正确的,因为它在http-request头中执行了以下内容类型:
Content-Type: application/json
如果你像我一样使用php,甚至使用Symfony2,你可以简单地扩展json标准的服务器兼容性:http://silex.sensiolabs.org/doc/cookbook/json_request_body.html
Symfony2方式(例如在你的DefaultController中):
$request = $this->getRequest();
if (0 === strpos($request->headers->get('Content-Type'), 'application/json')) {
$data = json_decode($request->getContent(), true);
$request->request->replace(is_array($data) ? $data : array());
}
var_dump($request->request->all());
好处是,你不需要使用jQuery参数,你可以使用AngularJS的原生方式来做这样的请求。
你可以全局定义行为:
$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
所以你不必每次都重新定义它:
$http.post("/handle/post", {
foo: "FOO",
bar: "BAR"
}).success(function (data, status, headers, config) {
// TODO
}).error(function (data, status, headers, config) {
// TODO
});