Adding a custom header to HTTP request using angular.js

JavascriptAngularjsHttp Headers

Javascript Problem Overview


I am a novice to angular.js, and I am trying to add some headers to a request:

   var config = {headers: {
            'Authorization': 'Basic d2VudHdvcnRobWFuOkNoYW5nZV9tZQ==',
            'Accept': 'application/json;odata=verbose'
        }
    };

   $http.get('https://www.example.com/ApplicationData.svc/Malls(1)/Retailers', config).success(successCallback).error(errorCallback);

I've looked at all the documentation, and this seems to me like it should be correct.

When I use a local file for the URL in the $http.get, I see the following HTTP request on the network tab in Chrome:

GET /app/data/offers.json HTTP/1.1
Host: www.example.com
Connection: keep-alive
Cache-Control: max-age=0
If-None-Match: "0f0abc9026855b5938797878a03e6889"
Authorization: Basic Y2hhZHN0b25lbWFuOkNoYW5nZV9tZQ==
Accept: application/json;odata=verbose
X-Requested-With: XMLHttpRequest
If-Modified-Since: Sun, 24 Mar 2013 15:58:55 GMT
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22
X-Testing: Testing
Referer: http://www.example.com/app/index.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

As you can see, both of the headers were added correctly. But when I change the URL to the one shown in the $http.get above (except using the real address, not example.com), then I get:

OPTIONS /ApplicationData.svc/Malls(1) HTTP/1.1
Host: www.datahost.net
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: http://mpon.site44.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22
Access-Control-Request-Headers: accept, origin, x-requested-with, authorization, x-testing
Accept: */*
Referer: http://mpon.site44.com/app/index.html
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

The only difference in code between these two is one is for the first the URL is a local file, and for the second the URL is a remote server. If you look at the second Request header, there is no Authentication header, and the Accept appears to be using a default instead of the one specified. Also, the first line now says OPTIONS instead of GET (although Access-Control-Request-Method is GET).

Any idea what is wrong with the above code, or how to get the additional headers included using when not using a local file as a data source?

Javascript Solutions


Solution 1 - Javascript

I took what you had, and added another X-Testing header

var config = {headers:  {
        'Authorization': 'Basic d2VudHdvcnRobWFuOkNoYW5nZV9tZQ==',
        'Accept': 'application/json;odata=verbose',
        "X-Testing" : "testing"
    }
};

$http.get("/test", config);

And in the Chrome network tab, I see them being sent.

GET /test HTTP/1.1
Host: localhost:3000
Connection: keep-alive
Accept: application/json;odata=verbose
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22
Authorization: Basic d2VudHdvcnRobWFuOkNoYW5nZV9tZQ==
X-Testing: testing
Referer: http://localhost:3000/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

Are you not seeing them from the browser, or on the server? Try the browser tooling or a debug proxy and see what is being sent out.

Solution 2 - Javascript

Basic authentication using HTTP POST method:

$http({
	method: 'POST',
	url: '/API/authenticate',
	data: 'username=' + username + '&password=' + password + '&email=' + email,
	headers: {
		"Content-Type": "application/x-www-form-urlencoded",
		"X-Login-Ajax-call": 'true'
	}
}).then(function(response) {
	if (response.data == 'ok') {
		// success
	} else {
		// failed
	}
});

...and GET method call with header:

$http({
	method: 'GET',
	url: '/books',
	headers: {
		'Authorization': 'Basic d2VudHdvcnRobWFuOkNoYW5nZV9tZQ==',
		'Accept': 'application/json',
		"X-Login-Ajax-call": 'true'
	}
}).then(function(response) {
	if (response.data == 'ok') {
		// success
	} else {
		// failed
	}
});

Solution 3 - Javascript

If you want to add your custom headers to ALL requests, you can change the defaults on $httpProvider to always add this header…

app.config(['$httpProvider', function ($httpProvider) {
    $httpProvider.defaults.headers.common = { 
        'Authorization': 'Basic d2VudHdvcnRobWFuOkNoYW5nZV9tZQ==',
        'Accept': 'application/json;odata=verbose'
      };
}]);

Solution 4 - Javascript

my suggestion will be add a function call settings like this inside the function check the header which is appropriate for it. I am sure it will definitely work. it is perfectly working for me.

function getSettings(requestData) {
    return {
        url: requestData.url,
        dataType: requestData.dataType || "json",
        data: requestData.data || {},
        headers: requestData.headers || {
            "accept": "application/json; charset=utf-8",
            'Authorization': 'Bearer ' + requestData.token
        },
        async: requestData.async || "false",
        cache: requestData.cache || "false",
        success: requestData.success || {},
        error: requestData.error || {},
        complete: requestData.complete || {},
        fail: requestData.fail || {}
    };
}

then call your data like this

    var requestData = {
        url: 'API end point',
        data: Your Request Data,
        token: Your Token
    };

    var settings = getSettings(requestData);
    settings.method = "POST"; //("Your request type")
    return $http(settings);

Solution 5 - Javascript

What you see for OPTIONS request is fine. Authorisation headers are not exposed in it.

But in order for basic auth to work you need to add: withCredentials = true; to your var config.

From the AngularJS $http documentation:

> withCredentials - {boolean} - whether to to set the withCredentials > flag on the XHR object. See requests with credentials for more > information.

Solution 6 - Javascript

And what's the answer from the server? It should reply a 204 and then really send the GET you are requesting.

In the OPTIONS the client is checking if the server allows CORS requests. If it gives you something different than a 204 then you should configure your server to send the correct Allow-Origin headers.

The way you are adding headers is the right way to do it.

Solution 7 - Javascript

Chrome is preflighting the request to look for CORS headers. If the request is acceptable, it will then send the real request. If you're doing this cross-domain, you will simply have to deal with it or else find a way to make the request non-cross-domain. This is by design.

> Unlike simple requests (discussed above), "preflighted" requests first > send an HTTP request by the OPTIONS method to the resource on the > other domain, in order to determine whether the actual request is safe > to send. Cross-site requests are preflighted like this since they may > have implications to user data. In particular, a request is > preflighted if: > > It uses methods other than GET, HEAD or POST. Also, if POST is used to > send request data with a Content-Type other than > application/x-www-form-urlencoded, multipart/form-data, or text/plain, > e.g. if the POST request sends an XML payload to the server using > application/xml or text/xml, then the request is preflighted. It sets > custom headers in the request (e.g. the request uses a header such as > X-PINGOTHER)

Ref: https://stackoverflow.com/questions/21783079/ajax-in-chrome-sending-options-instead-of-get-post-put-delete

Solution 8 - Javascript

You are just adding a header which server does not allow.

eg - your server is set up CORS to allow these headers only (accept,cache-control,pragma,content-type,origin)

and in your http request you are adding like this

 headers: {
        'Authorization': 'Basic d2VudHdvcnRobWFuOkNoYW5nZV9tZQ==',
        'Accept': 'application/json',
        'x-testing': 'testingValue'
    }

then the Server will reject this request since (Authorization and x-testing) are not allowed.

This is server side configuration.

And there is nothing to do with HTTP Options, it is just a preflight to server which is from different domain to check if server will allow actual call or not.

Solution 9 - Javascript

For me the following explanatory snippet worked. Perhaps you shouldn't use ' for header name?

{
   headers: { 
      Authorization: "Basic " + getAuthDigest(), 
      Accept: "text/plain" 
   }
}

I'm using $http.ajax(), though I wouldn't expect that to be a game changer.

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
QuestiontrentclowaterView Question on Stackoverflow
Solution 1 - JavascriptKevin HakansonView Answer on Stackoverflow
Solution 2 - JavascriptAjay KumarView Answer on Stackoverflow
Solution 3 - JavascriptKorayemView Answer on Stackoverflow
Solution 4 - JavascriptRiyadh Ul IslamView Answer on Stackoverflow
Solution 5 - JavascriptDmitry EvseevView Answer on Stackoverflow
Solution 6 - JavascriptghostbarView Answer on Stackoverflow
Solution 7 - JavascriptAsim K TView Answer on Stackoverflow
Solution 8 - JavascriptYeYintNaingView Answer on Stackoverflow
Solution 9 - JavascriptŁukaszBachmanView Answer on Stackoverflow