Angular $http POST request with request payload or form data

If you have RESTful API’s on your server side and are trying to use Angular’s $http service to consume the resource, you should be careful about how the request (for example, Http POST) is made, in particular how the data (perhaps in the format of form) is included in the request. As a JSON object or URL parameters? There is a difference between request payload and form data. The key word is “form data“.

Depending on how you design your RESTful API, if you probably read the data (http POST) from url params, you will need to transform your data from object not to JSON string, but to url params.

The Request Payload – or to be more precise: payload body of a HTTP Request – is the data normally send by a POST or PUT Request. It’s the part after the headers and the CRLF of a HTTP Request.

A request with Content-Type: application/json may look like this:

POST /some-path HTTP/1.1
Content-Type: application/json

{ "foo" : "bar", "name" : "John" }

If you submit this per AJAX the browser simply shows you what it is submitting as payload body. That’s all it can do because it has no idea where the data is coming from.

If you submit a HTML-Form with method="POST" and Content-Type: application/x-www-form-urlencoded or Content-Type: multipart/form-data your request may look like this:

POST /some-path HTTP/1.1
Content-Type: application/x-www-form-urlencoded

foo=bar&name=John

In this case the form-data is the request payload. Here the Browser knows more: it knows that bar is the value of the input-field foo of the submitted form. And that’s what it is showing to you.

So, they differ in the Content-Type but not in the way data is submitted. In both cases the data is in the message-body. And Chrome distinguishes how the data is presented to you in the Developer Tools.

By default, the $http service will transform the outgoing request by serializing the data as JSON and then posting it with the content- type, “application/json”. When we want to post the value as a FORM post, we need to change the serialization algorithm and post the data with the content-type, “application/x-www-form-urlencoded”.

$http({
    method: 'POST',
    url: url,
    headers: {'Content-Type': 'application/x-www-form-urlencoded'},
    transformRequest: function(obj) {
        var str = [];
        for(var p in obj)
        str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
        return str.join("&");
    },
    data: {username: $scope.userName, password: $scope.password}
}).success(function () {});

There is a good post on this
http://www.bennadel.com/blog/2615-posting-form-data-with-http-in-angularjs.htm

One quick personal note: you don’t need to write the format conversion yourself, JQuery has one for you already.

http://api.jquery.com/jquery.param/

For example:

var params = { width:1680, height:1050 };
var str = jQuery.param( params );

str now contains width=1680&height=1050