使用JavaScript访问网页的HTTP标头


Answers:


365

无法读取当前标题。您可以向同一URL发出另一个请求并读取其标头,但不能保证这些标头与当前URL完全相同。


使用以下JavaScript代码通过执行get请求来获取所有HTTP标头:

var req = new XMLHttpRequest();
req.open('GET', document.location, false);
req.send(null);
var headers = req.getAllResponseHeaders().toLowerCase();
alert(headers);

58
赛义德,也许不是最适合的问题笔者..我想这是因为它不访问加载资源的标题,但使一个新的请求。显然,他知道最好的,什么是最好的答案是,并使它自己
mykhal

18
根据您使用的标题之后,您可能希望使用“ HEAD”动词。
斯科特鲁迪2012年

17
仅在保证您需要的响应值在一个请求与下一个请求之间相同时,才可以发出新请求。这取决于您的应用程序,因此采用这种方法的里程会有所不同。
keparo

6
此hack在某些情况下可能会起作用,但是如果包含脚本的页面是为响应POST请求而生成的,则该hack根本不会起作用,并且如果您尝试确定服务器是否遇到错误也无济于事。 (HTTP 5XX),同时处理原始请求。
claymation

9
这个答案非常错误。正确的答案是“不可能”。或适合这个答案“不可能,但这是一种尝试模拟它的技巧,这可能对您完全无效”。

301

不幸的是,没有一个API可以为您的初始页面请求提供HTTP响应标头。那是这里发布的原始问题。也有人反复询问,因为有些人希望获得原始页面请求的实际响应标头而不发出另一个请求。


对于AJAX请求:

如果通过AJAX发出HTTP请求,则可以使用getAllResponseHeaders()方法获取响应标头。它是XMLHttpRequest API的一部分。要查看如何应用此fetchSimilarHeaders()功能,请查看以下功能。请注意,这是解决该问题的方法,对于某些应用程序来说并不可靠。

myXMLHttpRequest.getAllResponseHeaders();

这不会为您提供有关原始页面请求的HTTP响应标头的信息,但是可以用于对这些标头的含义进行有根据的猜测。接下来将对此进行更多描述。


从初始页面请求中获取标头值:

这个问题是几年前首次提出的,专门询问如何获取当前页面的原始HTTP响应标头(即运行javascript的同一页面)。与仅获取任何HTTP请求的响应标头相比,这是一个完全不同的问题。对于初始页面请求,标头不易用于javascript。如果您再次通过AJAX请求同一页,则所需的标头值是否可靠且足够一致将取决于您的特定应用程序。

以下是解决该问题的一些建议。


1.对资源的请求基本上是静态的

如果响应在很大程度上是静态的,并且标题在请求之间不会有太大变化,则可以对当前所在的同一页面发出AJAX请求,并假定它们是与页面相同的值。 HTTP响应。这可以允许您使用上述漂亮的XMLHttpRequest API访问所需的标头。

function fetchSimilarHeaders (callback) {
    var request = new XMLHttpRequest();
    request.onreadystatechange = function () {
        if (request.readyState === XMLHttpRequest.DONE) {
            //
            // The following headers may often be similar
            // to those of the original page request...
            //
            if (callback && typeof callback === 'function') {
                callback(request.getAllResponseHeaders());
            }
        }
    };

    //
    // Re-request the same page (document.location)
    // We hope to get the same or similar response headers to those which 
    // came with the current page, but we have no guarantee.
    // Since we are only after the headers, a HEAD request may be sufficient.
    //
    request.open('HEAD', document.location, true);
    request.send(null);
}

如果您确实必须依赖请求之间的值一致,则这种方法会出现问题,因为您不能完全保证它们是相同的。这将取决于您的特定应用程序,以及您是否知道所需的值不会从一个请求更改为另一个请求。


2.进行推论

一些BOM性质,其浏览器确定通过查看头(浏览器对象模型)。其中一些属性直接反映HTTP标头(例如navigator.userAgent,设置为HTTP User-Agent标头字段的值)。通过嗅探可用属性,您可能能够找到所需的内容,或一些线索来指示HTTP响应包含的内容。


3.藏起来

如果控制服务器端,则可以在构建完整响应时访问所需的任何标头。可以将值与页面一起传递给客户端,或者以某些标记或内置的JSON结构形式存储。如果您想让每个HTTP请求标头都可用于javascript,则可以在服务器上对其进行迭代,然后将它们作为隐藏值发送回标记中。以这种方式发送标头值可能并不理想,但是您可以针对所需的特定值进行发送。该解决方案也可以说是效率低下的,但是如果您需要它可以完成任务。


2
谷歌如何检测到它,像我在这里所说:stackoverflow.com/questions/7191242/...
kamaci

重新更新:ajax请求也是2008年Web开发方式的标准组成部分-_-
BlueRaja-Danny Pflughoeft 2012年

5
对于那些想知道的人,BOM代表“浏览器对象模型”。有关某些背景,请参见stackoverflow.com/questions/2213594/…
Myrne Stol

1
3)您也可以将它们存储在http cookie标头中。然后,您无需更改文档标记。
2014年

有一种简单的方法来访问响应标头元素,例如link元素:在此处使用文档示例:gist.github.com/FunThomas424242/…–
FunThomas424242


24

服务人员的解决方案

服务人员可以访问网络信息,包括标头。好消息是它可以用于任何类型的请求,而不仅仅是XMLHttpRequest。

怎么运行的:

  1. 在您的网站上添加服务人员。
  2. 观看正在发送的每个请求。
  3. fetch通过respondWith功能向服务人员发出请求。
  4. 响应到达时,读取标题。
  5. 使用功能将标头从服务工作者发送到页面postMessage

工作示例:

服务人员的理解有点复杂,因此我建立了一个小型库来完成所有这些工作。它可以在github上找到:https : //github.com/gmetais/sw-get-headers

局限性:

  • 该网站必须使用HTTPS
  • 浏览器需要支持Service Workers API
  • 相同域/跨域策略正在执行,就像XMLHttpRequest一样

12

对于那些寻求将所有HTTP标头解析为可以作为字典进行访问的对象的方法的人headers["content-type"],我创建了一个函数parseHttpHeaders

function parseHttpHeaders(httpHeaders) {
    return httpHeaders.split("\n")
     .map(x=>x.split(/: */,2))
     .filter(x=>x[0])
     .reduce((ac, x)=>{ac[x[0]] = x[1];return ac;}, {});
}

var req = new XMLHttpRequest();
req.open('GET', document.location, false);
req.send(null);
var headers = parseHttpHeaders(req.getAllResponseHeaders());
// Now we can do:  headers["content-type"]

10

将标头信息发送到JavaScript的另一种方法是通过cookie。服务器可以从请求标头中提取所需的任何数据,并将其发送回Set-Cookie响应标头中,并且可以在JavaScript中读取cookie。但是,正如keparo所说,最好只对一个或两个标头执行此操作,而不要对所有标头执行此操作。


1
这种方法仍然需要您控制JS的服务器。无论您如何交流这些信息,您的代码都会突然变得不可缓存。为什么不只为该特定请求创建API以避免破坏对原始资产的请求呢?
MST 2016年

5

如果我们谈论的是Request标头,则可以在执行XmlHttpRequests时创建自己的标头。

var request = new XMLHttpRequest();
request.setRequestHeader("X-Requested-With", "XMLHttpRequest");
request.open("GET", path, true);
request.send(null);

出于安全原因,您将无法在mozilla中修改请求标头。 mxr.mozilla.org/mozilla1.8.0/source/extensions/xmlextras/base/…– 2009
20:07

1
在使用setRequestHeader()方法之前,必须先调用open()。developer.mozilla.org/en/…–
XP1

1
在最初的问题中,访问是关于获取标头,而不是设置标头。
Timo Tijhof

4

您无法访问http标头,但是DOM中提供了其中提供的某些信息。例如,如果要查看http引用(原文如此),请使用document.referrer。对于其他http标头,可能还有其他类似的内容。尝试谷歌搜索所需的特定内容,例如“ http Referer javascript”。

我知道这应该很明显,但是当我真正想要的只是引荐来源时,我一直在搜索“ http标头javascript”之类的东西,但没有得到任何有用的结果。我不知道我是怎么意识到我可以进行更具体的查询的。


4

像许多人一样,我一直在挖掘网络,却没有真正的答案:(

不过,我发现了可以帮助他人的旁路。就我而言,我完全控制我的Web服务器。实际上,它是我的应用程序的一部分(请参阅最终参考)。我很容易将脚本添加到http响应中。我修改了httpd服务器,以便在每个html页面中注入一个小的脚本。我仅在头文件构造后立即添加了额外的“ js脚本”行,该行在浏览器中设置了文档中的现有变量[我选择位置],但是任何其他选项都是可行的。虽然我的服务器是用nodejs编写的,但毫无疑问,可以从PHP或其他方法中使用相同的技术。

  case ".html":
    response.setHeader("Content-Type", "text/html");
    response.write ("<script>location['GPSD_HTTP_AJAX']=true</script>")
    // process the real contend of my page

现在,从我的服务器加载的每个html页面都有一个由浏览器在接收时执行的脚本。然后,我可以轻松地从JavaScript检查该变量是否存在。在我的用例中,我需要知道是否应该使用JSON或JSON-P配置文件来避免CORS问题,但是相同的技术也可以用于其他目的[即:在开发/生产服务器之间进行选择,从服务器中获取REST / API钥匙等。]

在浏览器上,您仅需要直接从JavaScript检查变量,如我的示例所示,在该示例中,我使用它来选择我的Json / JQuery配置文件

 // Select direct Ajax/Json profile if using GpsdTracking/HttpAjax server otherwise use JsonP
  var corsbypass = true;  
  if (location['GPSD_HTTP_AJAX']) corsbypass = false;

  if (corsbypass) { // Json & html served from two different web servers
    var gpsdApi = "http://localhost:4080/geojson.rest?jsoncallback=?";
  } else { // Json & html served from same web server [no ?jsoncallback=]
    var gpsdApi = "geojson.rest?";
  }
  var gpsdRqt = 
      {key   :123456789 // user authentication key
      ,cmd   :'list'    // rest command
      ,group :'all'     // group to retreive
      ,round : true     // ask server to round numbers
   };
   $.getJSON(gpsdApi,gpsdRqt, DevListCB);

对于谁想要检查我的代码的人:https : //www.npmjs.org/package/gpsdtracking


3

使用mootools,您可以使用this.xhr.getAllResponseHeaders()


3

我刚刚进行了测试,并且使用Chrome版本28.0.1500.95对我有效。

我需要下载文件并读取文件名。文件名在标题中,因此我执行了以下操作:

var xhr = new XMLHttpRequest(); 
xhr.open('POST', url, true); 
xhr.responseType = "blob";
xhr.onreadystatechange = function () { 
    if (xhr.readyState == 4) {
        success(xhr.response); // the function to proccess the response

        console.log("++++++ reading headers ++++++++");
        var headers = xhr.getAllResponseHeaders();
        console.log(headers);
        console.log("++++++ reading headers end ++++++++");

    }
};

输出:

Date: Fri, 16 Aug 2013 16:21:33 GMT
Content-Disposition: attachment;filename=testFileName.doc
Content-Length: 20
Server: Apache-Coyote/1.1
Content-Type: application/octet-stream

2

这是我获取所有响应标头的脚本:

var url = "< URL >";

var req = new XMLHttpRequest();
req.open('HEAD', url, false);
req.send(null);
var headers = req.getAllResponseHeaders();

//Show alert with response headers.
alert(headers);

结果是响应头。

在此处输入图片说明

这是使用Hurl.it进行的比较测试:

在此处输入图片说明


2

要将标头作为更方便的对象(对Raja答案的改进):

var req = new XMLHttpRequest();
req.open('GET', document.location, false);
req.send(null);
var headers = req.getAllResponseHeaders().toLowerCase();
headers = headers.split(/\n|\r|\r\n/g).reduce(function(a, b) {
    if (b.length) {
        var [ key, value ] = b.split(': ');
        a[key] = value;
    }
    return a;
}, {});
console.log(headers);

2

Allain Lalonde的链接让我感到非常高兴。只需在此处添加一些简单的工作html代码即可。
早于IE9 +和Presto-Opera 12即可使用任何合理的浏览器。

<!DOCTYPE html>
<title>(XHR) Show all response headers</title>

<h1>All Response Headers with XHR</h1>
<script>
 var X= new XMLHttpRequest();
 X.open("HEAD", location);
 X.send();
 X.onload= function() { 
   document.body.appendChild(document.createElement("pre")).textContent= X.getAllResponseHeaders();
 }
</script>

注意:您将获得第二个请求的标头,其结果可能与初始请求不同。


另一种方式
是更现代的fetch()API
https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
caniuse.com它是Firefox 40,铬42,边缘14,Safari浏览器支持11
工作示例码:

<!DOCTYPE html>
<title>fetch() all Response Headers</title>

<h1>All Response Headers with fetch()</h1>
<script>
 var x= "";
 if(window.fetch)
    fetch(location, {method:'HEAD'})
    .then(function(r) {
       r.headers.forEach(
          function(Value, Header) { x= x + Header + "\n" + Value + "\n\n"; }
       );
    })
    .then(function() {
       document.body.appendChild(document.createElement("pre")).textContent= x;
    });
 else
   document.write("This does not work in your browser - no support for fetch API");
</script>

0

这是一个老问题。不知道什么时候支持变得更加广泛,但getAllResponseHeaders()getResponseHeader()似乎现在是相当标准:http://www.w3schools.com/xml/dom_http.asp


50
getAllResponseHeaders()和getResponseHeader()是XMLHttpRequest对象的方法。即针对ajax请求。您不能使用这些方法查看初始页面的标题-这就是我认为原始问题真正提出的内容。
asgeo1 2011年

-1

如前所述,如果您控制服务器端,则应该可以在初始响应中将初始请求标头发送回客户端。

例如,在Express中,以下工作:

app.get('/somepage', (req, res) => { res.render('somepage.hbs', {headers: req.headers}); }) 标头随后可在模板中使用,因此可以在视觉上隐藏,但包含在标记中,并由客户端javascript读取。


问题是询问响应头,而不是请求头。
昆汀

-1

我认为问题出了错,如果您想从JQuery / JavaScript中获取Request标头,答案就是“否”。其他解决方案是创建aspx页或jsp页,那么我们可以轻松地访问请求标头。将所有请求放在aspx页面中,并放入会话/ cookie中,然后就可以访问JavaScript页面中的cookie。


1
问题是关于读取响应头的问题。它仅在可能相关的问题的上下文中提及请求标头。
昆汀
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.