访问web页面's HTTP头在JavaScript

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

<强> < / >强这个问题相关,它被修改为询问访问两个特定的HTTP报头。

< p > 相关: < br > 如何通过JavaScript访问HTTP请求报头字段? < / p >
776993 次浏览

不幸的是,没有一个API为您的初始页面请求提供HTTP响应头。这是最初的问题。它也是反复问,因为有些人想要得到原始页面请求的实际响应头,而不发出另一个。


AJAX请求:

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

myXMLHttpRequest.getAllResponseHeaders();
  • API是在以下XMLHttpRequest的候选建议中指定的

  • 具体来说,getAllResponseHeaders()方法在以下部分中指定

  • MDN文档也很好:developer.mozilla.org XMLHttpRequest

这不会为您提供关于原始页面请求的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可用,你可以在服务器上遍历它们,并将它们作为隐藏值发送回标记中。以这种方式发送报头值可能并不理想,但您当然可以为所需的特定值这样做。这种解决方案也可以说是低效的,但如果您需要它,它可以完成工作。

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

如果我们谈论的是请求头文件,你可以在执行xmlhttprequest时创建自己的头文件。

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

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

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

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

这只是我的个人意见。

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

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

无法读取当前的头文件。您可以向相同的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);

您不能访问http报头,但是其中提供的一些信息在DOM中是可用的。例如,如果你想查看http引用器(原文如此),使用document.referrer。可能还有其他类似的http头文件。试着谷歌一下你想要的具体内容,比如“http referer javascript”。

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

我刚刚测试过,这适用于我使用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

和许多人一样,我一直在网上搜索,没有真正的答案:(

不过我找到了一条可以帮助别人的旁路。在我的情况下,我完全控制我的网络服务器。事实上,这是我的应用程序的一部分(见末尾参考)。这是很容易为我添加一个脚本到我的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 < / p >

Service worker的解决方案

Service worker能够访问包括头信息在内的网络信息。好处是它可以处理任何类型的请求,而不仅仅是XMLHttpRequest。

工作原理:

  1. 在你的网站上添加一个服务人员。
  2. 观察正在发送的每个请求。
  3. 使用respondWith函数将service worker fetch作为请求。
  4. 当响应到达时,读取报头。
  5. 使用postMessage函数将header从service worker发送到页面。

工作的例子:

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

限制:

  • 网站需要在HTTPS
  • 浏览器需要支持服务工作人员 API
  • 同域/跨域策略正在起作用,就像在XMLHttpRequest上一样

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

这是我的脚本,以获得所有的响应头:

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

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

以Express为例,以下工作:

< p > <代码>应用程序。Get ('/somepage', (req, res) =>{ res.render(“somepage。Hbs ', {headers: req.headers}); }) 这些头文件在模板中是可用的,因此可以在视觉上隐藏,但包含在标记中并由客户端javascript读取

将头文件作为一个更方便的对象获取(对拉贾的回答的改进):

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

我认为这个问题走错了方向, 如果你想从JQuery/JavaScript中获取Request头,答案是No。另一种解决方案是创建一个aspx页面或jsp页面,这样我们就可以很容易地访问请求头。 将aspx页面中的所有请求放到session/cookies中,然后可以访问JavaScript页面中的cookies .

Allain Lalonde的链接让我很开心。 只是在这里添加了一些简单的html代码。
适用于任何合理的浏览器,包括IE9+和preto - 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>

注意:你得到第二个请求的头,结果可能不同于最初的请求。

人力资源> < p > < 另一种方式
是更现代的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(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>

(2021)一个应答没有额外的HTTP调用

虽然在一般情况下不可能读取顶级HTML导航的任意HTTP响应头,如果你控制服务器(或中间箱),并希望将一些信息暴露给JavaScript,这些信息不能通过任何其他方式轻易暴露,只能通过头:

你可以使用Server-Timing头来公开任意键值数据,JavaScript可以读取它。

(*支持的浏览器:Firefox 61, Chrome 65, Edge 79;no Safari yet and no immediate plan for shipping as 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"

维基百科如何使用这个头文件来暴露缓存命中/未命中的信息:

维基百科上服务器定时响应头的使用

代码示例(需要考虑在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-Timing报头还支持dur(报头)字段,在JS端可读为duration,但它是可选的,如果不通过,在JS中默认为0
  • 关于Safari支持:参见错误1错误2错误3
  • 你可以在这篇博文中阅读更多关于服务器计时的内容
  • 注意,性能项缓冲区可能由页面上的JS清理(通过API调用),或者由浏览器清理(如果页面对子资源发出太多调用)。因此,你应该尽快捕获数据,和/或使用PerformanceObserver API代替。详见博客