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


89

我是angular.js的新手,并且尝试向请求添加一些标头:

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

我看了所有文档,在我看来这应该是正确的。

当我在中使用本地文件作为URL时$http.get,我在Chrome的“网络”标签上看到以下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

如您所见,两个标头均已正确添加。但是,当我将URL更改为$http.get上面显示的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

两者之间唯一的代码差异是一个,第一个URL是本地文件,第二个URL是远程服务器。如果查看第二个Request标头,则没有Authentication标头,并且Accept似乎使用的是默认名称,而不是指定的默认名称。此外,第一行现在显示,OPTIONS而不是GET(尽管Access-Control-Request-MethodGET)。

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


2
这看起来像是CORS的问题-请仔细阅读以下讨论的背景知识:groups.google.com/forum
topic

这确实是一个CORS问题。未将服务器配置为返回Access-Control-Allow-Origin:标头。如果您想在评论中写出答案以及有关CORS的详细信息,我会接受您的回答。以下来自Dmitry Evseev并由您编辑的答案很接近,但实际上并不是真正的问题。
trentclowater

1
如果请求是跨域的,Chrome将对请求进行预检以查找CORS标头。检查我的答案。
Asim KT

Answers:


66

我拿走了你的东西,并添加了另一个X-Testing标题

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

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

在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

您没有从浏览器或服务器上看到它们吗?尝试使用浏览器工具或调试代理,然后查看发送的内容。


我无权访问服务器,并且在浏览器上使用Firefox,但是我看到的是在上述原始问题中添加的标题。我看不到可以在Chrome的“资源”标签上查看标题的位置。
trentclowater

抱歉,我在您的答案中添加了一个修改内容,该修改旨在包含在我的原始问题中。
trentclowater

我指的是开发人员工具的网络标签,而不是资源-更新答案
Kevin Hakanson 2013年

我向问题添加了更多信息。似乎在一种情况下添加了标头,但在另一种情况下却未添加。
trentclowater

21

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

...以及带有标头的GET方法调用:

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

最好的答案。
尤达(Yoda)2018年

9

如果要将自定义标头添加到所有请求,则可以更改$ httpProvider的默认值以始终添加此标头…

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

除OPTIONS以外的所有请求都是
Rocco'Robco'16

很好的例子。可以用来缓存用于重定向页面的令牌吗?
Martian2049 '16

7

我的建议是在函数内部添加像这样的函数调用设置,检查适合它的标题。我敢肯定它将肯定有效。这对我来说是完美的。

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

然后像这样调用您的数据

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

2

您看到的OPTIONS请求很好。授权标头未在其中公开。

但是,为了基本的认证工作需要添加:withCredentials = true;给你的var config

从AngularJS $ http文档中

withCredentials - {boolean}-是否设置withCredentials XHR对象上的标志。有关更多信息,请参见带有凭据的请求


1

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

在OPTIONS中,客户端正在检查服务器是否允许CORS请求。如果它提供的内容不同于204,则应配置服务器以发送正确的Allow-Origin标头。

添加标题的方法是正确的方法。


1

Chrome正在预检查找CORS标头的请求。如果请求可以接受,它将发送真实请求。如果您正在执行此跨域操作,则只需处理它,否则将找到一种使请求成为非跨域请求的方法。这是设计使然。

与简单请求(如上所述)不同,“预检”请求首先通过OPTIONS方法将HTTP请求发送到另一个域上的资源,以确定实际请求是否可以安全发送。跨站点请求这样被预检,因为它们可能会影响用户数据。特别是在以下情况下,请求将被预检:

它使用GET,HEAD或POST以外的方法。另外,如果POST用于发送请求类型为application / x-www-form-urlencoded,multipart / form-data或text / plain之外的Content-Type的请求数据,例如POST请求将XML有效负载发送给服务器使用application / xml或text / xml,则对请求进行预检。它在请求中设置自定义标头(例如,请求使用标头,例如X-PINGOTHER)

参考:Chrome中的AJAX发送选项而不是GET / POST / PUT / DELETE吗?


-8

对我而言,以下解释性片段有效。也许您不应该使用'标题名称?

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

我正在使用$http.ajax(),尽管我不希望这会改变游戏规则。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.