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

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

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

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

Сейчас я перехожу к использованию Angular, и я хочу заменить этот вызов на $http.post. Я придумал следующее:

$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 предоставляет что-либо для этого из коробки.

Ответ 1

Я думаю, что параметр конфигурации params здесь не будет работать, поскольку он добавляет строку в url вместо тела, но для добавления к тому, что предлагает 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);
    }
});

Таким образом, все вызовы $http.post автоматически преобразуют тело в тот же формат параметров, который используется вызовом 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
    });

Ответ 2

При использовании 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';
});

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

$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 на конечных точках.

Ответ 3

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

params - {Object.} - Карта строк или объектов, которые будет повернут к? key1 = value1 & key2 = value2 после URL. Если Значение не является строкой, оно будет JSONified.

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

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

Подробнее см. .

Ответ 4

Используйте функцию 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.

Ответ 5

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

В app.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
});

Ответ 6

У меня также проблемы с настройкой настраиваемой 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 дня, чтобы понять это.

Ответ 7

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

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

Ответ 8

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

$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);

Ответ 9

   .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 () {});
    }
  ]);

Ответ 10

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

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

Ответ 12

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

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

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

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

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

Также может быть важно указать тип содержимого application/json в строке запроса с клиентской стороны.