使用angular.js向HTTP请求添加自定义头

时间:2022-06-20 12:30:33

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:

当我为$http中的URL使用本地文件时。get,我在Chrome的network选项卡上看到如下HTTP请求:

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:

如您所见,两个头都被正确地添加了。但是当我将URL更改为$http中显示的URL时。获得上面(除了使用真实地址,而不是example.com),然后我得到:

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).

这两个代码之间的唯一区别是,第一个URL是一个本地文件,第二个URL是一个远程服务器。如果查看第二个请求头,则不存在身份验证头,并且Accept似乎使用了一个默认值,而不是指定的那个。另外,第一行现在显示的是选项而不是GET(尽管Access-Control-Request-Method是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?

您知道上面的代码有什么问题吗?或者当不使用本地文件作为数据源时,如何获得包含的附加头文件?

8 个解决方案

#1


61  

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

我取了你所拥有的,并添加了另一个x测试头

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.

在Chrome网络标签中,我看到他们被发送了。

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.

你不是从浏览器或服务器上看到的吗?尝试浏览器工具或调试代理,看看会发送什么。

#2


18  

Basic authentication using HTTP POST method:

使用HTTP POST方法进行基本身份验证:

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

#3


7  

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

#4


7  

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

如果您想将您的自定义头添加到所有请求,您可以更改$httpProvider上的默认值,以始终添加这个头……

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

#5


2  

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.

但是为了基本的auth,你需要添加:withCredentials = true;你的var配置。

From the AngularJS $http documentation:

来自AngularJS $http文档:

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

凭据-{布尔}-是否在XHR对象上设置凭据标志。有关更多信息,请参见凭据请求。

#6


1  

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

服务器的答案是什么?它应该回复204,然后真正发送你所请求的GET。

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.

在选项中,客户端正在检查服务器是否允许CORS请求。如果它提供了与204不同的内容,那么您应该配置您的服务器以发送正确的允许值头。

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

添加header的方法是正确的。

#7


1  

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.

Chrome是长官的请求寻找CORS头。如果请求是可接受的,那么它将发送真正的请求。如果您正在进行这个跨域操作,那么您只需要处理它,或者找到一种方法使请求成为非跨域的。这是通过设计。

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:

与上面讨论的简单请求不同,“预置”请求首先通过OPTIONS方法向另一个域中的资源发送HTTP请求,以确定实际的请求是否安全。跨站点请求像这样预置,因为它们可能对用户数据有影响。特别是,如果:

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)

它使用的方法不是GET、HEAD或POST。另外,如果POST用于发送除application/ www-form- urlencodes、multipart/form-data或text/plain之外的内容类型的请求数据,例如,如果POST请求使用application/ XML或text/ XML向服务器发送XML有效负载,那么该请求是预先完成的。它在请求中设置自定义头(例如,请求使用一个头,如X-PINGOTHER)

Ref: AJAX in Chrome sending OPTIONS instead of GET/POST/PUT/DELETE?

引用:AJAX在Chrome发送选项而不是GET/POST/PUT/DELETE?

#8


-8  

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.

我使用的是$http.ajax(),但我不认为这会改变游戏规则。

#1


61  

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

我取了你所拥有的,并添加了另一个x测试头

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.

在Chrome网络标签中,我看到他们被发送了。

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.

你不是从浏览器或服务器上看到的吗?尝试浏览器工具或调试代理,看看会发送什么。

#2


18  

Basic authentication using HTTP POST method:

使用HTTP POST方法进行基本身份验证:

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

#3


7  

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

#4


7  

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

如果您想将您的自定义头添加到所有请求,您可以更改$httpProvider上的默认值,以始终添加这个头……

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

#5


2  

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.

但是为了基本的auth,你需要添加:withCredentials = true;你的var配置。

From the AngularJS $http documentation:

来自AngularJS $http文档:

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

凭据-{布尔}-是否在XHR对象上设置凭据标志。有关更多信息,请参见凭据请求。

#6


1  

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

服务器的答案是什么?它应该回复204,然后真正发送你所请求的GET。

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.

在选项中,客户端正在检查服务器是否允许CORS请求。如果它提供了与204不同的内容,那么您应该配置您的服务器以发送正确的允许值头。

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

添加header的方法是正确的。

#7


1  

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.

Chrome是长官的请求寻找CORS头。如果请求是可接受的,那么它将发送真正的请求。如果您正在进行这个跨域操作,那么您只需要处理它,或者找到一种方法使请求成为非跨域的。这是通过设计。

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:

与上面讨论的简单请求不同,“预置”请求首先通过OPTIONS方法向另一个域中的资源发送HTTP请求,以确定实际的请求是否安全。跨站点请求像这样预置,因为它们可能对用户数据有影响。特别是,如果:

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)

它使用的方法不是GET、HEAD或POST。另外,如果POST用于发送除application/ www-form- urlencodes、multipart/form-data或text/plain之外的内容类型的请求数据,例如,如果POST请求使用application/ XML或text/ XML向服务器发送XML有效负载,那么该请求是预先完成的。它在请求中设置自定义头(例如,请求使用一个头,如X-PINGOTHER)

Ref: AJAX in Chrome sending OPTIONS instead of GET/POST/PUT/DELETE?

引用:AJAX在Chrome发送选项而不是GET/POST/PUT/DELETE?

#8


-8  

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.

我使用的是$http.ajax(),但我不认为这会改变游戏规则。