AngularJS-любой способ для $ http.post для отправки параметров запроса вместо JSON?

у меня есть старый код, который делает запрос AJAX POST через метод post jQuery и выглядит так:

$.post("/foo/bar", requestData,
    function(responseData)
    {
        //do stuff with response
    }

requestData - это просто объект javascript с некоторыми базовыми строковыми свойствами.

Я в процессе перемещения наших вещей, чтобы использовать Angular, и я хочу заменить этот вызов $http.должность. Я придумал следующее:--10-->

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

когда я это сделал, я получил ответ об ошибке 500 от сервера. С помощью Firebug, я обнаружил, что это отправило тело запроса следующим образом:

{"param1":"value1","param2":"value2","param3":"value3"}

успешный jQuery $.post посылает тело так:

param1=value1&param2=value2&param3=value3

конечная точка, на которую я нажимаю, ожидает параметры запроса, а не JSON. Итак, мой вопрос в том, есть ли в любом случае сказать $http.post отправить объект javascript в качестве параметров запроса вместо JSON? Да, я знаю, что мог бы построить строку сам из объекта, но я хочу знать, предоставляет ли Angular что-нибудь для этого из коробка.

13 ответов


Я думаю params config параметр не будет работать здесь, так как он добавляет строку в url вместо тела, но добавить к тому, что Infeligo предложил здесь, является примером глобального переопределения преобразования по умолчанию (используя jQuery параметр в качестве примера для преобразования данных в строку param).

настройка глобальной функции transformRequest:

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

app.config(function ($httpProvider) {
    $httpProvider.defaults.transformRequest = function(data){
        if (data === undefined) {
            return data;
        }
        return $.param(data);
    }
});

таким образом, все вызовы $http.post автоматически преобразует тело в то же самое формат param, используемый jQuery $.post звонок.

Примечание Вы также можете установить заголовок Content-Type для каждого вызова или глобально, как это:

$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';

пример неглобального 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
    });

при использовании угловые >= 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';
});

и тогда вы можете сделать это в любом месте в вашем приложении:

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

и он будет правильно сериализовать данные как param1=value1&param2=value2 и отправить его в /requesturl С application/x-www-form-urlencoded; charset=utf-8 заголовок Content-Type, как обычно ожидается, с запросами POST на конечных точках.


из документации AngularJS:

params - {объект.} – Отображение строк или объектов, которые будут обращены ?key1=value1 & key2=value2 после url. если значение не является строкой, это будет JSONified.

Итак, укажите строку в качестве параметров. Если вы этого не хотите, используйте преобразования. Опять же, из документации:

чтобы переопределить эти преобразования локально, укажите функции преобразования как свойства transformRequest и / или transformResponse конфигурации объект. Чтобы глобально переопределить преобразования по умолчанию, переопределите $ httpProvider.по умолчанию.transformRequest и $ httpProvider.по умолчанию.свойства transformResponse из $ httpProvider.

смотрите документация для получения более подробной информации.


используйте jQuery $.param функция для сериализации данных JSON в requestData.

короче говоря, используя аналогичный код, как ваш:

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

для использования этого вы должны включить jQuery на свою страницу вместе с AngularJS.


обратите внимание, что с Angular 1.4 вы можете сериализовать данные формы без использования jQuery.

в приложение.js:

module.run(function($http, $httpParamSerializerJQLike) {
  $http.defaults.transformRequest.unshift($httpParamSerializerJQLike);
});

затем в вашем контроллере:

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

Это может быть немного взломать, но я избежал проблемы и преобразовал JSON в массив сообщений PHP на стороне сервера:

$_POST = json_decode(file_get_contents('php://input'), true);

У меня также есть проблемы с настройкой пользовательской аутентификации 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'}
      },
    }
);

надеюсь, я смог кому-то помочь. Мне потребовалось 3 дня, чтобы это понять.


изменить заголовки по умолчанию:

$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded;charset=utf-8";

тогда используйте jQuery $.param способ:

var payload = $.param({key: value});
$http.post(targetURL, payload);

   .controller('pieChartController', ['$scope', '$http', '$httpParamSerializerJQLike', function($scope, $http, $httpParamSerializerJQLike) {
        var data = {
                TimeStamp : "2016-04-25 12:50:00"
        };
        $http({
            method: 'POST',
            url: 'serverutilizationreport',
            headers: {'Content-Type': 'application/x-www-form-urlencoded'},
            data: $httpParamSerializerJQLike(data),
        }).success(function () {});
    }
  ]);

Быстрая настройка - для тех из вас, у кого возникли проблемы с глобальной конфигурацией функции transformRequest, вот фрагмент, который я использую, чтобы избавиться от Cannot read property 'jquery' of undefined ошибка:

$httpProvider.defaults.transformRequest = function(data) {
        return data != undefined ? $.param(data) : null;
    }

вы также можете решить эту проблему без изменения кода на сервере, изменив заголовок в $http.post и $_POST обычным способом. Объяснено здесь: http://victorblog.com/2012/12/20/make-angularjs-http-service-behave-like-jquery-ajax/


Я нашел много раз проблемное поведение этого целого. Я использовал его из express (без типизаций) и bodyParser (с типизациями DT~body-parser).

Я не пытался загрузить файл, а просто интерпретировать JSON, заданный в строке post.

на request.body был просто пустым json ({}).

после долгого расследования, наконец, это сработало для меня:

import { json } from 'body-parser';
...
app.use(json()); <-- should be defined before the first POST handler!

это может быть также важно, чтобы дать application/json введите содержимое строка запроса со стороны клиента.


синтаксис для AngularJS v1.4.8 + (v1.5.0)

       $http.post(url, data, config)
            .then(
                    function (response) {
                        // success callback
                    },
                    function (response) {
                        // failure callback
                    }
            );

например:

    var url = "http://example.com";

    var data = {
        "param1": "value1",
        "param2": "value2",
        "param3": "value3"
    };

    var config = {
        headers: {
            'Content-Type': "application/json"
        }
    };

    $http.post(url, data, config)
            .then(
                    function (response) {
                        // success callback
                    },
                    function (response) {
                        // failure callback
                    }
            );