在 Chrome 扩展中使用 AJAX 请求检测 URL 是不是支持 HTTP2?

Posted

技术标签:

【中文标题】在 Chrome 扩展中使用 AJAX 请求检测 URL 是不是支持 HTTP2?【英文标题】:Detect if URL supports HTTP2 using AJAX request in Chrome Extension?在 Chrome 扩展中使用 AJAX 请求检测 URL 是否支持 HTTP2? 【发布时间】:2017-05-06 04:46:06 【问题描述】:

我希望用户能够将他们的网站 URL 输入到作为 Chrome 扩展程序一部分的输入框中,并且 Chrome 扩展程序将使用 AJAX 请求或类似的东西来检测并告诉用户 URL 后面的服务器是否支持通过 HTTP2 发送响应。这可能吗?

也许 WebRequest 有办法获取这些信息?还是新的 Fetch API?您的请求能否以某种方式告诉服务器只有 HTTP2 回复被理解?我看不到明显的方法。

我知道你可以使用window.chrome.loadTimes().connectionInfo 来获取当前页面的协议,但这需要加载整个页面,我不想这样做。

示例网址:

通过 HTTP2 传送:https://cdn.sstatic.net/

通过 HTTP 1.1 交付:https://***.com/

【问题讨论】:

您可能可以通过API或解析响应使用一些在线测试工具,如KeyCDN。 @wOxxOm 这是一个选项,但如果扩展程序变得流行,我宁愿不必担心 API 密钥限制。 另一个想法(请不要问我详细信息,希望其他人会给出正确的答案):1)开始在 iframe 中加载 URL 2)使用 webRequest API 去除 X-Frame 标头从响应中 - 请参阅 *** 上的答案,3)在自动注入的内容脚本中立即中止加载(在清单中使用 "all_frames": true)并将带有 chrome.loadTimes().connectionInfo 的消息发送到您的背景/弹出脚本。 @fstr,您是否有使用 HTTP/2 来测试解决方案的网站列表(我可以找到一些,但您感兴趣的列表会有所帮助)?确认我的理解:您的用户在弹出窗口的输入框中输入了一个 URL,您希望能够通过更改该弹出窗口的 DOM 来告诉用户使用的协议(HTTP 1.1 或 HTTP/2)通过那个网址。您是否有一个minimal reproducible example,它实现了除围绕此场景的检查之外的所有内容?如果有,请提供。提供minimal reproducible example 将显着减少甚至开始测试解决方案所需的工作量。 @wOxxOm,鉴于希望在运行时使用用户提供的 URL,使用 tabs.executeScript() 将比 manifest.json 更合适 content_scripts 条目。使用 manifest.json content_scripts* entry here would be to have it load into ` 的唯一方法,这对于放置在用户打开的每个页面和框架上是不合适的负担。除此之外,该方法背后的一般概念似乎是可行的(各种改进,比 cmets 更适合答案)。 【参考方案1】:

HTTP/2 响应需要一个“状态”响应标头 - https://http2.github.io/http2-spec/#HttpResponse,因此要检查响应是否使用 HTTP/2,您可以在 extraInfoSpec 中使用带有 "responseHeaders"chrome.webRequest.onHeadersReceived 事件。例如,对于您的测试用例:

chrome.webRequest.onHeadersReceived.addListener(function(details) 
    var isHttp2 = details.responseHeaders.some(function(header) 
        return header.name === 'status';
    );
    console.log('Request to ' + details.url + ', http2 = ' + isHttp2);
, 
    urls: ['https://cdn.sstatic.net/*', 'http://***.com/*'],
    types: ['xmlhttprequest']
, ['responseHeaders']);

// Tests:
fetch('http://***.com');
fetch('https://cdn.sstatic.net');

【讨论】:

很好的观察!示例 URL 似乎是正确的。然而,这有多可靠?是否有任何 HTTP 1 服务器返回状态标头?其他协议会这样做吗? @fstr 它不是保留的标头,因此 HTTP/1 服务器也可以根据需要设置标头。如果你想得到最可靠的结果,你必须插入一个框架并覆盖几个响应头,包括 x-frame-options 和 content-security-policy。但是如果响应被重定向到其他地方(例如到另一个域),你将不知道服务器是否支持 HTTP/2。【参考方案2】:

编辑:显然您可以使用 iframe 和 webRequest 技巧来做到这一点!我找到了一个参考要点(但我自己还没有测试过):

https://gist.github.com/dergachev/e216b25d9a144914eae2

老答案

如果没有外部 API,您可能无法做到这一点。这就是为什么

1) 使用ajax只需要被测url的服务器将CORS headers返回给用户,否则浏览器不会接受。

2) 您可以即时创建 iframe 并在 iframe contentWindow 中使用 chrome.loadTimes().connectionInfo,但如果服务器发送 X-Frame-Options: Deny 标头,浏览器将不允许您加载 url在 iframe 中。

3) 通过webRequest API 剥离X-frame 标头,如此处所述

Getting around X-Frame-Options DENY in a Chrome extension?

可能无法正常工作,afaik Chrome 扩展不允许修改响应正文。

可能的解决方案

1) 上述问题可以使用添加适当标头的简单代理来解决。这是关于如何使用 nginx 进行操作的参考

http://balaji-damodaran.com/programming/2015/07/30/nginx-headers.html

2) 只需创建一个自定义 API,在服务器端执行请求并解析结果以检查 http2 支持。如果您的扩展程序变得流行,它仍然可以很容易地扩展它,例如通过缓存和水平扩展。

希望这会有所帮助!

【讨论】:

您确定不能去掉 x-frame-options 标头吗?我已经使用 webrequests API 去除了 x-frame-options + CSP 标头,以允许 iframe 显示在内部 Chrome 扩展页面中,并且它按预期工作。 实际上你可能是对的。我找到了一个可以做到这一点的扩展chrome.google.com/webstore/detail/ignore-x-frame-headers/…(请参阅上面的编辑答案以获取代码参考)

以上是关于在 Chrome 扩展中使用 AJAX 请求检测 URL 是不是支持 HTTP2?的主要内容,如果未能解决你的问题,请参考以下文章

Chrome 扩展:如何更改 AJAX 请求标头中的来源?

Chrome 扩展 ajax 发送格式错误的重音字符

Django 在 JQuery AJAX 请求中说 is_ajax 是错误的

如何在 laravel 4 中调试 ajax

如何在 Chrome 扩展中使用 Javascript 获取文件大小?

Postman 如何发送请求? ajax,同源策略