Webextension:如何透明地修改XMLHttpRequests [英] Webextension: How to transparently modify XMLHttpRequests

查看:63
本文介绍了Webextension:如何透明地修改XMLHttpRequests的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标

…将具有一个Web扩展(目前在Firefox中),以尽可能透明地拦截和修改站点的XMLHttpRequests问题.最好的情况是,即使明确寻找扩展名,该站点也无法检测到该扩展名.例如,我希望能够在发送关键数据之前自动对其进行编辑/替换,或者对大型图像进行高速缓存,尽管原始页面明确将其禁用.

原始方法

使用后台脚本和带有 blocking browser.webRequest 来拦截所有请求.

  browser.webRequest.onBeforeRequest.addListener(ModifySend,{网址:[< all_urls>"],},[阻止","requestBody"]);browser.webRequest.onResponseStarted.addListener(ModifyReceive,{网址:[< all_urls>"],},[阻止","responseHeaders"]); 

这在某种程度上起作用.尽管我可以查看,但无法更改发送(POST)的内容,并且Firefox会忽略(某些?)已更改的接收标头.例如,我无法覆盖 cache-control ,原始值仍然有效.

内容脚本

因为我只对XMLHttpRequest感兴趣,所以为什么没有内容脚本按照另一个问题中的建议修改 .不幸的是,内容脚本是与运行它们的页面隔离的,并且可以检测到注入的脚本.更改响应头的问题也没有解决.

问题

拦截和修改XMLHttpRequests的正确方法是什么?有可能达到我想要的程度吗?并作为扩展:如何提供大数据blob作为响应,例如,当我不能说服浏览器忽略不缓存"标头时自己进行缓存?

解决方案

最后,我使用了两种单独的方法.一种用于提供大数据blob,另一种用于 XMLHttpRequest 拦截.

内容斑点

最简单的选项似乎以将脚本插入页面.注入的脚本覆盖 XMLHttpRequest open 函数:

content.js

  function injectJS(file){令D =文档;让s = D.createElement('script');s.type ="text/javascript";s.src = browser.runtime.getURL(file);s.onload = function(){s.parentNode.removeChild(s);};(D.head || D.documentElement).appendChild(s);}injectJS("inject.js"); 

inject.js(单独的文件,在 web_accessible_resources 中)

 让realOpen = window.XMLHttpRequest.prototype.open;window.XMLHttpRequest.prototype.open = function(){let方法= arguments [0];让url = arguments [1];...realOpen.apply(this,arguments);}; 

My goal

… is to have a web extension (in Firefox for now) that intercepts and modified XMLHttpRequests issues by a site as transparently as possible. Best case is that the extension is undetectable by the site even when explicitly looking for it. For example, I want to be able to automatically redact/replace critical data before it is send out or enforce caching of large images despite the original page disabling that explicitly.

Original approach

Use a background script and browser.webRequest with blocking to intercept all requests.

browser.webRequest.onBeforeRequest.addListener(
  modifySend,
  {
    urls: ["<all_urls>"],
  },
  ["blocking", "requestBody"]
);

browser.webRequest.onResponseStarted.addListener(
  modifyReceive,
  {
    urls: ["<all_urls>"],
  },
  ["blocking", "responseHeaders"]
);

This works to some degree. While I can view all requests, changing the content of sends (POST) is not possible and (some?) changed headers of received are ignored by Firefox. For example I was not able to overwrite cache-control, the original value was still effective.

Content scripts

Since I'm only interested in XMLHttpRequests why not have a content script modify those as suggested in another question. Unfortunately, content scripts are isolated from the page they run in and injected scripts are detectable. The problem of changing response headers is also not solved.

Questions

What is the proper way to intercept and modify XMLHttpRequests? Is it even possible to the degree I want? And as an extension: How to I provide large data blobs as a response, for example if I do my own caching when I cannot persuade the browser to ignore "no caching" headers?

解决方案

In the end, I used two separate approaches. One for providing large data blobs and one for XMLHttpRequest interception.

Content blobs

The easiest option seems to provide the data as web_accessible_resources and then use the extension's background script to enforce redirects:

function serveLocally(details)
{
  const localRes = browser.runtime.getManifest().web_accessible_resources;
  let ret = {};

  localRes.forEach(file => {
    if (details.url.endsWith(file))
    {
      ret.redirectUrl = browser.runtime.getURL(file);
    }
  });
  return ret;
}

Interception

Here I use a content script which injects a script into the page. The injected script overwrites the open function of XMLHttpRequest:

content.js

function injectJS(file) {

  let D = document;
  let s = D.createElement('script');

  s.type = "text/javascript";
  s.src = browser.runtime.getURL(file);
  s.onload = function() {
    s.parentNode.removeChild(s);
  };

  (D.head || D.documentElement).appendChild(s);
}

injectJS("inject.js");

inject.js (separate file and among the web_accessible_resources)

let realOpen = window.XMLHttpRequest.prototype.open;

window.XMLHttpRequest.prototype.open = function() {
  let method = arguments[0];
  let url = arguments[1];
  ...  
  realOpen.apply(this, arguments);
};

这篇关于Webextension:如何透明地修改XMLHttpRequests的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆