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¶m2=value2¶m3=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¶m2=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;
}
Ответ 11
Вы также можете решить эту проблему без изменения кода на сервере, изменения заголовка в вызове $http.post
и регулярного использования $_POST
. Разъяснение здесь: http://victorblog.com/2012/12/20/make-angularjs-http-service-behave-like-jquery-ajax/
Ответ 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
в строке запроса с клиентской стороны.