在JavaScript中访问网页的HTTP标头

时间:2008-10-20 22:54:39

标签: javascript http http-headers

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

this question相关,已被修改为询问有关访问两个特定HTTP标头的信息。

  

相关:
  How do I access the HTTP request header fields via JavaScript?

18 个答案:

答案 0 :(得分:345)

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


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

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

答案 1 :(得分:278)

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


对于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 :(得分:27)

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

最好的情况是只执行HEAD请求,然后检查标题。

有关执行此操作的一些示例,请查看http://www.jibbering.com/2002/4/httprequest.html

只需2美分。

答案 3 :(得分:16)

Service Workers

的解决方案

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

工作原理:

  1. 在您的网站上添加服务工作者。
  2. 观看发送的每个请求。
  3. 使用fetch函数向服务工作者respondWith发送请求。
  4. 当响应到达时,请阅读标题。
  5. 将服务工作者的标题发送到具有postMessage功能的页面。
  6. 工作示例:

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

    限制:

    • 网站需要在 HTTPS
    • 浏览器需要支持Service Workers API
    • 同一域/跨域策略正在运行,就像在XMLHttpRequest
    • 上一样

答案 4 :(得分:9)

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

答案 5 :(得分:9)

对于那些寻找将所有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"]

答案 6 :(得分:5)

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

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

答案 7 :(得分:4)

您无法访问http标头,但DOM中提供了一些提供的信息。例如,如果要查看http referer(sic),请使用document.referrer。对于其他http标头,可能还有其他像这样的人。尝试使用Google搜索您想要的特定内容,例如“http referer javascript”。

我知道这应该是显而易见的,但我一直在寻找像“http header javascript”这样的东西,当我真正想要的只是引用者时,并没有得到任何有用的结果。我不知道我怎么没有意识到我可以提出更具体的问题。

答案 8 :(得分:3)

无需额外的 HTTP 调用

虽然通常不可能读取顶级 HTML 导航的任意 HTTP 响应标头,但如果您控制服务器(或途中的中间件)并希望向 JavaScript 公开一些信息除了通过标题外,其他任何方式都不能轻易暴露:

您可以使用 Server-Timing 标头公开任意键值数据,并且 JavaScript 可以读取这些数据。

(*支持的浏览器:Firefox 61、Chrome 65、Edge 79;截至 2021.02 尚无 Safari;无 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 如何使用此标头公开缓存命中/未命中信息的示例:

Usage of server-timing response header on 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

注意事项:

  • as mentioned on MDN,API 仅通过 HTTPS 支持
  • 如果您的 JS 是从另一个域提供的,您必须添加 Timing-Allow-Origin 响应标头以使数据对 JS 可读(Timing-Allow-Origin: *Timing-Allow-Origin: https://www.example.com
  • Server-Timing 标头还支持 dur(header) 字段,在 JS 端可读为 duration,但它是可选的,如果未通过,则在 JS 中默认为 0
  • 关于 Safari 支持:参见 bug 1bug 2bug 3
  • 您可以在 this blog post
  • 中阅读有关服务器计时的更多信息
  • 请注意,如果页面对子资源发出过多调用,页面上的 JS(通过 API 调用)或浏览器可能会清除性能条目缓冲区。因此,您应该尽快捕获数据,和/或改用 PerformanceObserver API。有关详细信息,请参阅 blog post

答案 9 :(得分:3)

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

但我发现了一个可以帮助他人的旁路。在我的情况下,我完全控制我的Web服务器。实际上它是我的应用程序的一部分(参见最终参考)。我很容易将一个脚本添加到我的http响应中。我修改了我的httpd服务器,在每个html页面中注入一个小脚本。我只在我的标题构造之后推送了一个额外的'js script'行,它在我的浏览器中设置了我的文档中的现有变量[我选择位置],但是任何其他选项都是可能的。虽然我的服务器是用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

答案 10 :(得分: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

答案 11 :(得分:3)

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

答案 12 :(得分:2)

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

答案 13 :(得分: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);

结果是响应头。

enter image description here

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

enter image description here

答案 14 :(得分:2)

将标头作为更方便使用的对象(Raja's answer的改进):

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

答案 15 :(得分:0)

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,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(v,i) {x+= (i+ "\t\t"+ v+ "\n")});
   }).then(function() {
     document.body.appendChild(document.createElement("pre")).textContent= x;
   })
</script>

答案 16 :(得分:-1)

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

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

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

答案 17 :(得分:-1)

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