467

如何通过 JavaScript 访问页面的 HTTP 响应标头?

与此问题相关,该问题已修改为询问有关访问两个特定 HTTP 标头的问题。

相关:
如何通过 JavaScript 访问 HTTP 请求标头字段?

4

18 回答 18

401

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


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

var req = new XMLHttpRequest();
req.open('GET', document.location, false);
req.send(null);
var headers = req.getAllResponseHeaders().toLowerCase();
alert(headers);
于 2011-02-03T01:26:52.083 回答
328

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


对于 AJAX 请求:

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

myXMLHttpRequest.getAllResponseHeaders();

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


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

这个问题是几年前首次提出的,专门询问如何获取当前页面(即运行 javascript 的同一页面)的原始 HTTP 响应标头。这是一个与简单地获取任何 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,设置为 HTTPUser-Agent标头字段的值)。通过嗅探可用的属性,您可能能够找到您需要的东西,或者一些指示 HTTP 响应包含的内容的线索。


3. 把它们藏起来

如果您控制服务器端,则可以在构建完整响应时访问您喜欢的任何标头。值可以与页面一起传递给客户端,隐藏在一些标记中,或者可能是内联的 JSON 结构。如果您想让每个 HTTP 请求标头都可用于您的 javascript,您可以在服务器上遍历它们并将它们作为标记中的隐藏值发送回来。以这种方式发送标头值可能并不理想,但您当然可以针对您需要的特定值执行此操作。这个解决方案也可以说是低效的,但如果你需要它,它可以完成这项工作。

于 2008-10-20T22:55:12.477 回答
31

使用XmlHttpRequest您可以拉出当前页面,然后检查响应的 http 标头。

最好的情况是只做一个HEAD请求,然后检查标头。

有关这样做的一些示例,请查看http://www.jibbering.com/2002/4/httprequest.html

只是我的2美分。

于 2008-11-03T21:53:37.983 回答
30

Service Worker 的解决方案

服务工作者能够访问网络信息,其中包括标头。好的部分是它适用于任何类型的请求,而不仅仅是 XMLHttpRequest。

这个怎么运作:

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

工作示例:

服务工作者理解起来有点复杂,所以我构建了一个小型库来完成所有这些工作。它在 github 上可用:https ://github.com/gmetais/sw-get-headers 。

限制:

  • 该网站需要使用HTTPS
  • 浏览器需要支持Service Workers API
  • 同域/跨域策略在起作用,就像在 XMLHttpRequest 上一样
于 2016-06-11T10:19:03.070 回答
18

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

于 2008-10-20T23:34:06.923 回答
14

对于那些寻找将所有 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"]
于 2017-12-09T01:11:13.847 回答
13

(2021)无需额外 HTTP 调用的答案

虽然通常无法读取顶级 HTML 导航的任意 HTTP 响应标头,但如果您控制服务器(或途中的中间盒)并希望向 JavaScript 公开一些无法在任何其他方式中轻松公开的信息方式比通过标题:

您可以使用Server-Timingheader 来公开任意键值数据,并且它可以被 JavaScript 读取。

(*在支持的浏览器中:Firefox 61、Chrome 65、Edge 79;还没有 Safari,也没有从 2021.09 开始立即发货的计划;没有 IE)

例子:

server-timing: key;desc="value"
server-timing: key1;desc="value1"
server-timing: key2;desc="value2"
  • 或使用其紧凑版本,在一个标头中公开多条数据,以逗号分隔。
server-timing: key1;desc="value1", key2;desc="value2"

Wikipedia如何使用此标头来公开有关缓存命中/未命中信息的示例:

在 Wikipedia 上使用服务器计时响应标头

代码示例(需要考虑 Safari 和 IE 缺乏浏览器支持):

if (window.performance && performance.getEntriesByType) { // avoid error in Safari 10, IE9- and other old browsers
    let navTiming = performance.getEntriesByType('navigation')
    if (navTiming.length > 0) { // still not supported as of Safari 14...
        let serverTiming = navTiming[0].serverTiming
        if (serverTiming && serverTiming.length > 0) {
            for (let i=0; i<serverTiming.length; i++) {
                console.log(`${serverTiming[i].name} = ${serverTiming[i].description}`)
            }
        }
    }
}

这会登录cache = hit-front支持的浏览器。

笔记:

  • 如 MDN所述,API 仅支持 HTTPS
  • 如果您的 JS 是从另一个域提供的,则必须添加Timing-Allow-Origin响应标头以使数据对 JS 可读(Timing-Allow-Origin: *Timing-Allow-Origin: https://www.example.com
  • Server-Timingheaders 还支持dur(header) 字段,duration在 JS 端可读,但它是可选的,0如果未传递,则默认为 JS
  • 关于 Safari 支持:请参阅错误 1​​和错误 2错误 3
  • 您可以在此博客文章中阅读有关服务器计时的更多信息
  • 请注意,如果页面对子资源发出过多调用,性能条目缓冲区可能会被页面上的 JS(通过 API 调用)或浏览器清理。因此,您应该尽快捕获数据,和/或改用PerformanceObserverAPI。有关详细信息,请参阅博客文章
于 2021-02-15T16:15:39.957 回答
6

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

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

于 2013-01-30T00:06:00.910 回答
5

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

var request = new XMLHttpRequest();
request.setRequestHeader("X-Requested-With", "XMLHttpRequest");
request.open("GET", path, true);
request.send(null);
于 2008-10-21T05:44:30.670 回答
5

阿兰·拉隆德的链接让我很开心。只需在此处添加一些简单的工作 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
Per caniuse.com它支持 Firefox 40、Chrome 42、Edge 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>
于 2019-11-10T18:57:30.603 回答
4

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

尽管如此,我还是找到了可以帮助其他人的旁路。就我而言,我完全控制了我的网络服务器。事实上,它是我的应用程序的一部分(见最终参考)。我很容易将脚本添加到我的 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

于 2014-10-15T11:36:47.800 回答
4

将标题作为一个更方便的对象(改进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;
}, {});
于 2018-08-14T13:16:00.700 回答
3

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

于 2008-11-10T12:37:16.963 回答
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
于 2013-08-16T16:29:57.137 回答
3

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

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 的比较测试:

在此处输入图像描述

于 2017-12-12T22:34:56.083 回答
-1

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

于 2011-01-31T02:17:32.610 回答
-1

正如已经提到的,如果您控制服务器端,那么应该可以在初始响应中将初始请求标头发送回客户端。

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

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

于 2018-03-25T01:58:56.420 回答
-2

我认为这个问题走错了路,如果你想从 JQuery/JavaScript 中获取请求标头,答案很简单。其他解决方案是创建一个 aspx 页面或 jsp 页面,然后我们可以轻松访问请求标头。将 aspx 页面中的所有请求放入会话/cookies 中,然后您可以访问 JavaScript 页面中的 cookie。

于 2018-12-05T17:02:36.863 回答