61

Angular is not adding the correct content type option, I tried the following command:

$http({
    url: "http://localhost:8080/example/teste",
    dataType: "json",
    method: "POST",
    headers: {
        "Content-Type": "application/json"
    }
}).success(function(response){
    $scope.response = response;
}).error(function(error){
    $scope.error = error;
});

The code above generates the following http request:

POST http://localhost:8080/example/teste HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 0
Cache-Control: no-cache
Pragma: no-cache
Origin: http://localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31
Content-Type: application/xml
Accept: application/json, text/plain, */*
X-Requested-With: XMLHttpRequest
Referer: http://localhost:8080/example/index
Accept-Encoding: gzip,deflate,sdch
Accept-Language: pt-BR,pt;q=0.8,en-US;q=0.6,en;q=0.4
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Cookie: JSESSIONID=C404CE2DA653136971DD1A3C3EB3725B

As you can see, instead of "application/json", the content type is "application/xml". Am I missing something here ?

raonirenosto
  • 1,507
  • 5
  • 19
  • 30

6 Answers6

96

You need to include a body with the request. Angular removes the content-type header otherwise.

Add data: '' to the argument to $http.

Josh Lee
  • 171,072
  • 38
  • 269
  • 275
  • 3
    but what if I want to send an object as data? I am working with an ASP.NET Generic HTTP handler, and for some reason, `context.Request.Params["formData"]` does not work, but a StackOverflow post led me to use `string json = new StreamReader(context.Request.InputStream).ReadToEnd();` which works, but I am not exactly relieved to use it since I would rather access the submitted request parameter value by name. – Web User Apr 13 '15 at 04:23
  • 2
    God this is a life saver!!! Is this the default HTTP protocol behavior or Angular $http behavior? – addlistener Aug 16 '15 at 09:24
  • For anyone using [Restangular](https://github.com/mgonto/restangular), here is an example of how to implement this solution: https://gist.github.com/sscovil/3bd0da1d98397213df54 – Shaun Scovil Sep 11 '15 at 14:23
  • 1
    @josh-lee why do we need to provide `data: ''` ? its pretty strange to me. what about GET request ? any idea ? – Aman Gupta Oct 17 '16 at 07:49
30
$http({
    url: 'http://localhost:8080/example/teste',
    dataType: 'json',
    method: 'POST',
    data: '',
    headers: {
        "Content-Type": "application/json"
    }

}).success(function(response){
    $scope.response = response;
}).error(function(error){
    $scope.error = error;
});

Try like this.

fcm
  • 6,305
  • 5
  • 24
  • 37
  • 3
    I am afraid it doesn't work in Angular 1.3.14, `Content-Type` is removed if there is no `data`. Empty `data` parameter solves the issue though... – IProblemFactory Apr 24 '15 at 13:24
  • Very Strange ! even for GET request also I had to provide the data: '' field. though we all know GET should not have a body ! any idea why angularjs is stripping off the content-type application/header when no data is provided ? – Aman Gupta Oct 17 '16 at 07:47
4
         $http({
                method: 'GET',
                url:'/http://localhost:8080/example/test' + toto,
                data: '',
                headers: {
                    'Content-Type': 'application/json'
                }
            }).then(
                function(response) {
                    return response.data;
                }, 
                function(errResponse) {
                    console.error('Error !!');
                    return $q.reject(errResponse);
                }
mezmah
  • 51
  • 2
2

Great! The solution given above worked for me. Had the same problem with a GET call.

 method: 'GET',
 data: '',
 headers: {
        "Content-Type": "application/json"
 }
mansoor.khan
  • 2,309
  • 26
  • 39
user1429957
  • 265
  • 2
  • 5
  • 1
    Please add some formatting to your code snippets. And explain yourself better to avoid down votes – simonmorley Dec 11 '15 at 11:43
  • GET request cannot have a body (http://stackoverflow.com/a/983458/2416700) so Content-Type is meaningless in this case – Evgeny Jan 14 '16 at 09:43
  • this is true that GET request cannot have a body, but strange when providing data as empty string then only content-type is taken other wise angularjs is strip off that header. !! – Aman Gupta Oct 17 '16 at 07:46
2

In case it's useful to anyone. For AngularJS 1.5x I wanted to set CSRF for all requests and I found that when I did this:

$httpProvider.defaults.headers.get = { 'CSRF-Token': afToken }; 
$httpProvider.defaults.headers.put = { 'CSRF-Token': afToken };
$httpProvider.defaults.headers.post = { 'CSRF-Token': afToken }; 

Angular removed the content type so I had to add this:

$httpProvider.defaults.headers.common = { "Content-Type": "application/json"};

Otherwise I get a 415 media type error.

So I am doing this to configure my application for all requests:

angular.module("myapp.maintenance", [])
    .controller('maintenanceCtrl', MaintenanceCtrl)
    .directive('convertToNumber', ConvertToNumber)
    .config(configure);

MaintenanceCtrl.$inject = ["$scope", "$http", "$sce", "$window", "$document", "$timeout", "$filter", 'alertService'];
configure.$inject = ["$httpProvider"];

// configure the header tokens for  CSRF for http operations in this module
function configure($httpProvider) {

    const afToken = angular.element('input[id="__AntiForgeryToken"]').attr('value');

    $httpProvider.defaults.headers.get = { 'CSRF-Token': afToken }; // only added for GET
    $httpProvider.defaults.headers.put = { 'CSRF-Token': afToken }; // added for PUT
    $httpProvider.defaults.headers.post = { 'CSRF-Token': afToken }; // added for POST

    // for some reason if we do the above we have to set the default content type for all 
    // looks like angular clears it when we add our own headers
    $httpProvider.defaults.headers.common = { "Content-Type": "application/json" };

}
Norbert Norbertson
  • 2,102
  • 1
  • 16
  • 28
0

Just to show an example of how to dynamically add the "Content-type" header to every POST request. In may case I'm passing POST params as query string, that is done using the transformRequest. In this case its value is application/x-www-form-urlencoded.

// set Content-Type for POST requests
angular.module('myApp').run(basicAuth);
function basicAuth($http) {
    $http.defaults.headers.post = {'Content-Type': 'application/x-www-form-urlencoded'};
}

Then from the interceptor in the request method before return the config object

// if header['Content-type'] is a POST then add data
'request': function (config) {
  if (
    angular.isDefined(config.headers['Content-Type']) 
    && !angular.isDefined(config.data)
  ) {
    config.data = '';
  }
  return config;
}
aUXcoder
  • 1,048
  • 1
  • 20
  • 32