【问题标题】:How to modify http request headers based on user options in a Chrome extension?如何根据 Chrome 扩展中的用户选项修改 http 请求标头?
【发布时间】:2021-05-17 21:47:04
【问题描述】:

我正在开发我的第一个 Google Chrome 扩展程序。我想根据用户可以在我的扩展程序的选项页面上选择的选项向(所有)http(s) 请求添加自定义标头。

我成功管理了以下内容:

  1. 为所有 http 请求手动添加自定义标头
  2. 创建选项页面
  3. chrome.storage.sync 中的保存和恢复选项

现在我正在努力将上述内容结合起来。这是我尝试过的:

chrome.webRequest.onBeforeSendHeaders.addListener(function(details){
    var demoOptions = new Array();
    var demoHeader = '';
    var bkg = chrome.extension.getBackgroundPage(); // for debugging
    chrome.storage.sync.get({
    demoOption: true,
    }, function(items) {
        if(items.demoOption){
            demoOptions.push('demo-header-1');
        }
        demoHeader = demoOptions.join();
        details.requestHeaders.push({
            name: 'X-Demo-Header',
            value: demoHeader //this is not showing up in the http headers
        });
        bkg.console.log('demoHeader:' + demoHeader); //this is putting the correct value to the debugging console
        bkg.console.log(details.requestHeaders); //this is putting the headers to the debugging console, incl. x-demo-header1 and x-demo-header2 (see below)
    });

    details.requestHeaders.push({
        name: 'X-Demo-Header2',
        value: 'Demo-Header-2' //this is correctly added to the headers and included in the request
    });
    
    return { requestHeaders: details.requestHeaders };
},
{urls: [ "*://*/*" ]},['requestHeaders','blocking']);

观察:

  1. X-Demo-Header2 已正确插入(在 Chrome 标头检查和调试控制台中可见)
  2. x-demo-header1 不是发送到站点的标头的一部分,但在调试输出中可见
  3. x-demo-header2 在标头中 before X-Demo-Header1 在控制台标头数组中(见截图)

假设:获取我的选项的函数(项目)是异步执行的,并且在插入我的选项的标头之前返回 requestHeaders。

我可以避免这种情况吗?有没有更好的选项来根据选项添加标题?

截图:

【问题讨论】:

    标签: javascript google-chrome google-chrome-extension


    【解决方案1】:

    TL;DR

    目前无法在 Chrome 中运行(2021 年 2 月 15 日)

    长答案

    JavaScript 在很大程度上依赖于异步代码执行的思想。在您的代码中,您在chrome.storage.sync.get(key, listener) 中注册的事件侦听器完成之前返回{ requestHeaders: details.requestHeaders }。所以demo-header-1添加得太晚了。

    这就是你需要使用 Promise 的原因。 docs 中有一个示例如何做到这一点。在该页面上向下滚动到它显示的位置:“此代码与前面的示例完全相同,只是侦听器是异步的,返回一个使用新标头解析的 Promise”

    在您的情况下,您的代码的修改版本如下所示:

    chrome.webRequest.onBeforeSendHeaders.addListener(
      function (details) {
        return new Promise((resolve, reject) => {
          chrome.storage.sync.get({ demoOption: true }, function (items) {
            if (items.demoOption) {
              details.requestHeaders.push({
                name: 'X-Demo-Header',
                value: 'demo-header-1',
              });
            }
            resolve({ requestHeaders: details.requestHeaders });
          });
        });
      },
      { urls: ['*://*/*'] },
      ['blocking', 'requestHeaders']
    );
    

    如你所见,我们现在返回一个 Promise 而不是一个对象字面量。在这个 Promise 中,我们等待chrome.storage.sync.get 的读取操作完成。完成后,我们解决 Promise。

    这应该在支持它的浏览器中工作。

    在 Chrome 中这不起作用,因为:

    There is no support in Chrome for returning a Promise from webRequest.onBeforeSendHeaders since 2018

    除非您能找到以同步方式从chrome.storage.sync.get 加载数据的方法,否则恐怕您会不走运。

    作为最后的手段,您可以尝试在 Chromium issue 中发布投诉。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-17
      • 2014-01-18
      • 2016-05-23
      • 1970-01-01
      • 2011-04-27
      • 2011-03-22
      • 2012-11-19
      • 1970-01-01
      相关资源
      最近更新 更多