Javascript 使用fetch时,如何选择退出HTTP/2服务器推送?
我正在用Javascript编写一个使用新FetchAPI的基本应用程序。以下是代码相关部分的基本示例:Javascript 使用fetch时,如何选择退出HTTP/2服务器推送?,javascript,google-chrome-extension,http2,fetch-api,Javascript,Google Chrome Extension,Http2,Fetch Api,我正在用Javascript编写一个使用新FetchAPI的基本应用程序。以下是代码相关部分的基本示例: function foo(url) { const options = {}; options.credentials = 'omit'; options.method = 'get'; options.headers = {'Accept': 'text/html'}; options.mode = 'cors'; options.cache = 'default'
function foo(url) {
const options = {};
options.credentials = 'omit';
options.method = 'get';
options.headers = {'Accept': 'text/html'};
options.mode = 'cors';
options.cache = 'default';
options.redirect = 'follow';
options.referrer = 'no-referrer';
options.referrerPolicy = 'no-referrer';
return fetch(url, options);
}
在发出提取请求时,我偶尔会看到控制台中出现如下错误:
拒绝加载脚本“”,因为它违反了以下内容安全策略指令
在阅读和学习了一些关于HTTP/2的知识之后,看起来出现了这条消息,因为响应正在推回一个预加载的脚本。使用devtools,我可以在响应中看到以下标题:
链接:;rel=预载;as=脚本
以下是我的Chrome扩展名的manifest.json文件的相关部分:
{
"content_security_policy": "script-src 'self'; object-src 'self'"
}
以下是有关Chrome的manifest.json格式的文档,以及如何将内容安全策略应用于扩展进行的获取:
我做了一些测试,并能够确定此错误消息发生在获取期间,而不是稍后解析响应文本时。在将脚本元素加载到活动DOM中时不存在任何问题,这一切都发生在获取时
我在研究中没有发现的是如何避免这种行为。看起来,在急于支持这个伟大的新特性时,制作HTTP/2和FETCH的人没有考虑到我不是为了显示它或它的任何相关资源(如CSS/MIV/Script)而获取远程页面的用例。I(应用程序)以后将不再使用任何相关资源;只有资源本身的内容
在我的用例中,这种推送(1)完全是浪费资源,(2)现在导致控制台中偶尔出现一条非常烦人的、导致压力的消息
话虽如此,这里有一个问题我希望得到一些帮助:是否有一种方法可以使用清单或脚本向浏览器发出信号,表明我对HTTP/2推送不感兴趣?我是否可以为fetch请求设置一个头,告诉web服务器不要用push响应?我是否可以在我的应用程序清单中使用CSP设置,以某种方式触发do not push me响应
我已经看了第3.3节,它没有多大帮助。我看到我可以发送像Link:;rel=预载;as=脚本;nopush
。问题是,我还不知道响应中将包含哪些链接头,而且我也不确定fetch是否允许在初始请求中设置链接头。我想知道我是否可以发送一些类型的请求,这些请求可以看到响应中的链接头,但可以避免它们,然后发送一个追加所有适当的nopush头的后续请求
下面是一个简单的测试用例来重现这个问题:
- 我不想使用代理服务器。明确解释为什么这是我唯一的选择是一个可以接受的答案
- 我不知道在配置CSP时将获取哪些URL
- 请参阅相关部分中的哪些说明“设置\u启用\u推送(0x2):此设置可用于禁用服务器推送(第8.2节)。如果端点收到此参数设置为的值,则不得发送推送承诺帧 有没有办法从脚本或清单中指定此设置,或者将其烘焙到Chrome中
chrome.webRequest
拦截对扩展请求的响应OnHeadersReceived
的阻止形式来去除包含rel=preload
SETTINGS\u ENABLE\u PUSH
的附加说明中所提到的,事实上,这些内容中的大部分都被嵌入了chrome浏览器中,隐藏在我们的视线之外。如果你想深入挖掘,我在chrome://net-internals/#http2
。也许Chrome正在删除服务器推送发送的文件,这些文件在初始响应中没有相应的链接头
此解决方案取决于chrome.webRequest
扩展的背景脚本:
let trackedUrl;
function foo(url) {
trackedUrl = url;
const options = {};
options.credentials = 'omit';
options.method = 'get';
options.headers = { 'Accept': 'text/html' };
options.mode = 'cors';
options.cache = 'default';
options.redirect = 'follow';
options.referrer = 'no-referrer';
options.referrerPolicy = 'no-referrer';
return fetch(url, options)
}
chrome.webRequest.onHeadersReceived.addListener(function (details) {
let newHeaders;
if (details.url.indexOf(trackedUrl) > -1) {
newHeaders = details.responseHeaders.filter(header => {
return header.value.indexOf('rel=preload') < 0;
})
}
return { responseHeaders: newHeaders };
}, { urls: ['<all_urls>'] }, ['responseHeaders', 'blocking']);
let trackedrl;
函数foo(url){
trackedrl=url;
常量选项={};
options.credentials='omit';
options.method='get';
options.headers={'Accept':'text/html'};
options.mode='cors';
options.cache='default';
options.redirect='follow';
options.referer='无推荐人';
options.refererPolicy='no referer';
返回获取(url、选项)
}
chrome.webRequest.onHeadersReceived.addListener(函数(细节){
让新的标题;
if(details.url.indexOf(trackedUrl)>-1){
newHeaders=details.responseHeaders.filter(header=>{
返回header.value.indexOf('rel=preload')<0;
})
}
返回{responseHeaders:newHeaders};
},{url:['
你可能还想更具体地说明你删除了哪些标题。我觉得删除所有链接会有一些额外的效果
这避免了代理,并且不需要在请求中设置链接头
这是一个非常强大的扩展,
{
"manifest_version": 2,
"name": "Example",
"description": "WebRequest Blocking",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png"
},
"background": {
"scripts": [
"back.js"
]
},
"content_security_policy": "script-src 'self'; object-src 'self'",
"permissions": [
"<all_urls>",
"background",
"webRequest",
"webRequestBlocking"
]
}