AngularJS - $ http.post发送请求参数而不是JSON的任何方式?

dnc*_*253 116 javascript jquery post angularjs

我有一些旧的代码通过jQuery的post方法发出一个AJAX POST请求,看起来像这样:

$.post("/foo/bar", requestData,
    function(responseData)
    {
        //do stuff with response
    }
Run Code Online (Sandbox Code Playgroud)

requestData 只是一个具有一些基本字符串属性的javascript对象.

我正在将我们的东西移动到使用Angular,我想用$ http.post替换这个调用.我想出了以下内容:

$http.post("/foo/bar", requestData).success(
    function(responseData) {
        //do stuff with response
    }
});
Run Code Online (Sandbox Code Playgroud)

当我这样做时,我收到了来自服务器的500错误响应.使用Firebug,我发现这样就发送了请求体:

{"param1":"value1","param2":"value2","param3":"value3"}
Run Code Online (Sandbox Code Playgroud)

成功的jQuery $.post发送身体像这样:

param1=value1&param2=value2&param3=value3
Run Code Online (Sandbox Code Playgroud)

我遇到的端点是期望请求参数而不是JSON.所以,我的问题是,无论如何要告诉$http.post发送javascript对象作为请求参数而不是JSON?是的,我知道我可以自己从对象构造字符串,但我想知道Angular是否提供了开箱即用的东西.

Glo*_*opy 140

我认为paramsconfig参数在这里不起作用,因为它将字符串添加到url而不是body,但是添加到Infeligo建议的是一个默认变换的全局覆盖的示例(使用jQuery param作为转换的示例)数据到param字符串).

设置全局transformRequest函数:

var app = angular.module('myApp');

app.config(function ($httpProvider) {
    $httpProvider.defaults.transformRequest = function(data){
        if (data === undefined) {
            return data;
        }
        return $.param(data);
    }
});
Run Code Online (Sandbox Code Playgroud)

这样所有对$ http.post的调用都会自动将主体转换为jQuery $.post调用所使用的相同param格式.

请注意,您可能还希望为每个调用设置Content-Type标头,或者像这样全局设置:

$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
Run Code Online (Sandbox Code Playgroud)

每次调用示例非全局transformRequest:

    var transform = function(data){
        return $.param(data);
    }

    $http.post("/foo/bar", requestData, {
        headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},
        transformRequest: transform
    }).success(function(responseData) {
        //do stuff with response
    });
Run Code Online (Sandbox Code Playgroud)


Sae*_*ini 21

如果使用Angular> = 1.4,这是我发现的最简洁的解决方案,它不依赖于任何自定义或外部:

angular.module('yourModule')
  .config(function ($httpProvider, $httpParamSerializerJQLikeProvider){
    $httpProvider.defaults.transformRequest.unshift($httpParamSerializerJQLikeProvider.$get());
    $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8';
});
Run Code Online (Sandbox Code Playgroud)

然后,您可以在应用中的任何位置执行此操作:

$http({
  method: 'POST',
  url: '/requesturl',
  data: {
    param1: 'value1',
    param2: 'value2'
  }
});
Run Code Online (Sandbox Code Playgroud)

它将正确序列化数据param1=value1&param2=value2并将其发送到/requesturlapplication/x-www-form-urlencoded; charset=utf-8Content-Type头,因为它是常与端点POST请求的预期.


Inf*_*igo 17

来自AngularJS文档:

params - {Object.} - 在url之后将转向的字符串或对象的映射?key1 = value1&key2 = value2.如果该值不是字符串,则它将是JSONified.

因此,提供字符串作为参数.如果您不想这样,那么使用转换.再次,从文档:

要在本地覆盖这些转换,请将转换函数指定为配置对象的transformRequest和/或transformResponse属性.要全局覆盖默认转换,请覆盖$ httpProvider的$ httpProvider.defaults.transformRequest和$ httpProvider.defaults.transformResponse属性.

有关详细信息,请参阅文档.


小智 15

使用jQuery的$.param函数来序列化requestData中的JSON数据.

简而言之,使用与您类似的代码:

$http.post("/foo/bar",
$.param(requestData),
{
    headers:
    {
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
    }
}
).success(
    function(responseData) {
        //do stuff with response
    }
});
Run Code Online (Sandbox Code Playgroud)

要使用它,您必须在页面中包含jQuery以及AngularJS.


Tho*_*ani 7

请注意,从Angular 1.4开始,您可以在不使用jQuery的情况下序列化表单数据.

在app.js中:

module.run(function($http, $httpParamSerializerJQLike) {
  $http.defaults.transformRequest.unshift($httpParamSerializerJQLike);
});
Run Code Online (Sandbox Code Playgroud)

然后在你的控制器中:

$http({
    method: 'POST',
    url: myUrl',
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    data: myData
});
Run Code Online (Sandbox Code Playgroud)


小智 5

我也有设置自定义http身份验证的问题,因为$ resource缓存了请求.

要使其工作,您必须通过执行此操作覆盖现有标头

var transformRequest = function(data, headersGetter){
  var headers = headersGetter();
  headers['Authorization'] = 'WSSE profile="UsernameToken"';
  headers['X-WSSE'] = 'UsernameToken ' + nonce
  headers['Content-Type'] = 'application/json';
};

return $resource(
  url,
    {
    },
    {
      query: {
        method: 'POST',
        url: apiURL + '/profile',
        transformRequest: transformRequest,
        params: {userId: '@userId'}
      },
    }
);
Run Code Online (Sandbox Code Playgroud)

我希望我能帮助别人.我花了3天时间才想出这个.


Tim*_*olo 5

这可能是一个黑客,但我避免了这个问题,并将json转换为服务器端的PHP的POST数组:

$_POST = json_decode(file_get_contents('php://input'), true);
Run Code Online (Sandbox Code Playgroud)