AngularJS - Any way for $http.post to send request parameters instead of JSON?

JavascriptJqueryPostAngularjs

Javascript Problem Overview


I have some old code that is making an AJAX POST request through jQuery's post method and looks something like this:

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

requestData is just a javascript object with some basic string properties.

I'm in the process of moving our stuff over to use Angular, and I want to replace this call with $http.post. I came up with the following:

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

When I did this, I got a 500 error response from the server. Using Firebug, I found that this sent the request body like this:

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

The successful jQuery $.post sends the body like this:

param1=value1&param2=value2&param3=value3

The endpoint I am hitting is expecting request parameters and not JSON. So, my question is is there anyway to tell $http.post to send up the javascript object as request parameters instead of JSON? Yes, I know I could construct the string myself from the object, but I want to know if Angular provides anything for this out of the box.

Javascript Solutions


Solution 1 - Javascript

I think the params config parameter won't work here since it adds the string to the url instead of the body but to add to what Infeligo suggested here is an example of the global override of a default transform (using jQuery param as an example to convert the data to param string).

Set up global transformRequest function:

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

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

That way all calls to $http.post will automatically transform the body to the same param format used by the jQuery $.post call.

Note you may also want to set the Content-Type header per call or globally like this:

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

Sample non-global transformRequest per call:

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

Solution 2 - Javascript

If using Angular >= 1.4, here's the cleanest solution I've found that doesn't rely on anything custom or external:

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';
});

And then you can do this anywhere in your app:

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

And it will correctly serialize the data as param1=value1&param2=value2 and send it to /requesturl with the application/x-www-form-urlencoded; charset=utf-8 Content-Type header as it's normally expected with POST requests on endpoints.

Solution 3 - Javascript

From AngularJS documentation:

> params – {Object.} – Map of strings or objects which > will be turned to ?key1=value1&key2=value2 after the url. If the > value is not a string, it will be JSONified.

So, provide string as parameters. If you don't want that, then use transformations. Again, from the documentation:

> To override these transformation locally, specify transform functions > as transformRequest and/or transformResponse properties of the config > object. To globally override the default transforms, override the > $httpProvider.defaults.transformRequest and > $httpProvider.defaults.transformResponse properties of the > $httpProvider.

Refer to documentation for more details.

Solution 4 - Javascript

Use jQuery's $.param function to serialize the JSON data in requestData.

In short, using similar code as yours:

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

For using this, you have to include jQuery in your page along with AngularJS.

Solution 5 - Javascript

Note that as of Angular 1.4, you can serialize the form data without using jQuery.

In the app.js:

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

Then in your controller:

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

Solution 6 - Javascript

I have problems as well with setting custom http authentication because $resource cache the request.

To make it work you have to overwrite the existing headers by doing this

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'}
      },
    }
);

I hope I was able to help someone. It took me 3 days to figure this one out.

Solution 7 - Javascript

This might be a bit of a hack, but I avoided the issue and converted the json into PHP's POST array on the server side:

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

Solution 8 - Javascript

Modify the default headers:

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

Then use JQuery's $.param method:

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

Solution 9 - Javascript

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

Solution 10 - Javascript

Quick adjustment - for those of you having trouble with the global configuration of the transformRequest function, here's the snippet i'm using to get rid of the Cannot read property 'jquery' of undefined error:

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

Solution 11 - Javascript

You can also solve this problem without changing code in server, changing header in $http.post call and use $_POST the regular way. Explained here: http://victorblog.com/2012/12/20/make-angularjs-http-service-behave-like-jquery-ajax/

Solution 12 - Javascript

I found many times problematic behavior of this whole. I used it from express (without typings) and the bodyParser (with the dt~body-parser typings).

I didn't try to upload a file, instead simply to interpret a JSON given in a post string.

The request.body was simply an empty json ({}).

After a lot of investigation finally this worked for me:

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

It may be also important to give the application/json content type in the request string from the client side.

Solution 13 - Javascript

Syntax for AngularJS v1.4.8 + (v1.5.0)

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

Eg:

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questiondnc253View Question on Stackoverflow
Solution 1 - JavascriptGloopyView Answer on Stackoverflow
Solution 2 - JavascriptSaeb AminiView Answer on Stackoverflow
Solution 3 - JavascriptInfeligoView Answer on Stackoverflow
Solution 4 - JavascriptSagar BhosaleView Answer on Stackoverflow
Solution 5 - JavascriptThomas GrazianiView Answer on Stackoverflow
Solution 6 - JavascriptFrank MarceloView Answer on Stackoverflow
Solution 7 - JavascriptTimoSoloView Answer on Stackoverflow
Solution 8 - JavascriptZagsView Answer on Stackoverflow
Solution 9 - JavascriptRohit LuthraView Answer on Stackoverflow
Solution 10 - Javascriptkshep92View Answer on Stackoverflow
Solution 11 - Javascriptvikramaditya234View Answer on Stackoverflow
Solution 12 - JavascriptpeterhView Answer on Stackoverflow
Solution 13 - JavascriptpvrforpranavvrView Answer on Stackoverflow