如何通过JavaScript访问页面的HTTP响应头?
与此问题相关,该问题已被修改为询问访问两个特定的HTTP报头。
相关: 如何通过JavaScript访问HTTP请求报头字段?
如何通过JavaScript访问页面的HTTP响应头?
与此问题相关,该问题已被修改为询问访问两个特定的HTTP报头。
相关: 如何通过JavaScript访问HTTP请求报头字段?
当前回答
不幸的是,没有一个API为您的初始页面请求提供HTTP响应头。这是最初的问题。它也被反复要求,因为有些人希望获得原始页面请求的实际响应头,而不需要发出另一个页面请求。
对于AJAX请求:
如果HTTP请求是通过AJAX发出的,则可以使用getAllResponseHeaders()方法获得响应头。它是XMLHttpRequest API的一部分。要了解如何应用它,请查看下面的fetchSimilarHeaders()函数。请注意,这是对某些应用程序不可靠的问题的一种变通方法。
myXMLHttpRequest.getAllResponseHeaders();
该API在以下XMLHttpRequest候选推荐中指定:XMLHttpRequest - W3C候选推荐3 2010年8月 具体来说,getAllResponseHeaders()方法在以下部分中指定 MDN文档也很好:developer.mozilla.org: XMLHttpRequest。
这不会为您提供关于原始页面请求的HTTP响应标头的信息,但可以用来对这些标头进行有根据的猜测。下面将详细介绍。
从初始页面请求中获取头值:
This question was first asked several years ago, asking specifically about how to get at the original HTTP response headers for the current page (i.e. the same page inside of which the javascript was running). This is quite a different question than simply getting the response headers for any HTTP request. For the initial page request, the headers aren't readily available to javascript. Whether the header values you need will be reliably and sufficiently consistent if you request the same page again via AJAX will depend on your particular application.
下面是一些解决这个问题的建议。
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报头(例如导航器)。userAgent被设置为HTTP User-Agent报头字段的值)。通过嗅探可用属性,您可能能够找到您需要的东西,或者一些指示HTTP响应包含什么的线索。
3.藏
If you control the server side, you can access any header you like as you construct the full response. Values could be passed to the client with the page, stashed in some markup or perhaps in an inlined JSON structure. If you wanted to have every HTTP request header available to your javascript, you could iterate through them on the server and send them back as hidden values in the markup. It's probably not ideal to send header values this way, but you could certainly do it for the specific value you need. This solution is arguably inefficient, too, but it would do the job if you needed it.
其他回答
(2021)一个没有额外HTTP调用的应答
一般来说,读取顶级HTML导航的任意HTTP响应头是不可能的,如果你控制了服务器(或中间箱),想要向JavaScript公开一些信息,而这些信息只能通过头来公开:
可以使用Server-Timing报头公开任意键值数据,JavaScript可以读取这些数据。
(*支持的浏览器:Firefox 61, Chrome 65, Edge 79;目前还没有Safari浏览器,也没有在2021年9月发布的计划;没有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如何使用这个报头来暴露缓存命中/错过的信息:
代码示例(需要考虑在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, the API is only supported over HTTPS if your JS is served from another domain, you have to add Timing-Allow-Origin response header to make the data readable to JS (Timing-Allow-Origin: * or Timing-Allow-Origin: https://www.example.com) Server-Timing headers support also dur(header) field, readable as duration on JS side, but it's optional and defaults to 0 in JS if not passed regarding Safari support: see bug 1 and bug 2 and bug 3 You can read more on server-timing in this blog post Note that performance entries buffers might get cleaned by JS on the page (via an API call), or by the browser, if the page issues too many calls for subresources. For that reason, you should capture the data as soon as possible, and/or use PerformanceObserver API instead. See the blog post for details.
不幸的是,没有一个API为您的初始页面请求提供HTTP响应头。这是最初的问题。它也被反复要求,因为有些人希望获得原始页面请求的实际响应头,而不需要发出另一个页面请求。
对于AJAX请求:
如果HTTP请求是通过AJAX发出的,则可以使用getAllResponseHeaders()方法获得响应头。它是XMLHttpRequest API的一部分。要了解如何应用它,请查看下面的fetchSimilarHeaders()函数。请注意,这是对某些应用程序不可靠的问题的一种变通方法。
myXMLHttpRequest.getAllResponseHeaders();
该API在以下XMLHttpRequest候选推荐中指定:XMLHttpRequest - W3C候选推荐3 2010年8月 具体来说,getAllResponseHeaders()方法在以下部分中指定 MDN文档也很好:developer.mozilla.org: XMLHttpRequest。
这不会为您提供关于原始页面请求的HTTP响应标头的信息,但可以用来对这些标头进行有根据的猜测。下面将详细介绍。
从初始页面请求中获取头值:
This question was first asked several years ago, asking specifically about how to get at the original HTTP response headers for the current page (i.e. the same page inside of which the javascript was running). This is quite a different question than simply getting the response headers for any HTTP request. For the initial page request, the headers aren't readily available to javascript. Whether the header values you need will be reliably and sufficiently consistent if you request the same page again via AJAX will depend on your particular application.
下面是一些解决这个问题的建议。
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报头(例如导航器)。userAgent被设置为HTTP User-Agent报头字段的值)。通过嗅探可用属性,您可能能够找到您需要的东西,或者一些指示HTTP响应包含什么的线索。
3.藏
If you control the server side, you can access any header you like as you construct the full response. Values could be passed to the client with the page, stashed in some markup or perhaps in an inlined JSON structure. If you wanted to have every HTTP request header available to your javascript, you could iterate through them on the server and send them back as hidden values in the markup. It's probably not ideal to send header values this way, but you could certainly do it for the specific value you need. This solution is arguably inefficient, too, but it would do the job if you needed it.
无法读取当前的头文件。您可以向相同的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);
如前所述,如果您控制服务器端,那么应该可以在初始响应中将初始请求头发送回客户端。
以Express为例,以下工作:
App.get ('/somepage', (req, res) => { res.render(“somepage。Hbs ', {headers: req.headers}); }) 然后在模板中可以使用头文件,因此可以在视觉上隐藏,但包含在标记中并由客户端javascript读取。
如果我们讨论的是请求标头,您可以在执行xmlhttprequest时创建自己的标头。
var request = new XMLHttpRequest();
request.setRequestHeader("X-Requested-With", "XMLHttpRequest");
request.open("GET", path, true);
request.send(null);