92

是否可以创建修改 HTTP 响应正文的 Chrome 扩展程序?

我查看了Chrome Extension APIs,但我没有找到任何可以做到这一点的东西。

4

6 回答 6

55

通常,您无法使用标准 Chrome 扩展 API 更改 HTTP 请求的响应正文。

104058 请求此功能:WebRequest API:允许扩展编辑响应正文。为问题加注星标以获取更新通知。

如果要编辑 known 的响应正文,请XMLHttpRequest通过内容脚本注入代码XMLHttpRequest以使用自定义(全功能)构造函数覆盖默认构造函数,该构造函数在触发真实事件之前重写响应。确保您的 XMLHttpRequest 对象与 Chrome 的内置对象完全兼容XMLHttpRequest,否则 AJAX 繁重的网站将会崩溃。

在其他情况下,您可以使用chrome.webRequestchrome.declarativeWebRequestAPI 将请求重定向到data:-URI。与 XHR 方法不同,您不会获得请求的原始内容。实际上,请求永远不会到达服务器,因为重定向只能在实际请求发送之前完成。如果您重定向main_frame请求,用户将看到data:-URI 而不是请求的 URL。

于 2013-08-19T14:16:58.340 回答
28

我刚刚发布了一个可以做到这一点的 Devtools 扩展 :)

它被称为篡改,它基于mitmproxy,它允许您查看当前选项卡发出的所有请求,修改它们并在下次刷新时提供修改后的版本。

这是一个相当早期的版本,但它应该与 OS X 和 Windows 兼容。让我知道它是否不适合你。

你可以在这里得到它http://dutzi.github.io/tamper/

这是如何工作的

正如@Xan 在下面评论的那样,该扩展通过 Native Messaging 与扩展mitmproxy的 python 脚本进行通信。

该扩展使用 列出所有请求chrome.devtools.network.onRequestFinished

当您单击请求时,它会使用请求对象的getContent()方法下载其响应,然后将该响应发送到将其保存在本地的 python 脚本。

然后它在编辑器中打开文件(call用于 OSX 或subprocess.PopenWindows)。

python 脚本使用 mitmproxy 侦听通过该代理进行的所有通信,如果它检测到对已保存文件的请求,它会提供已保存的文件。

我使用 Chrome 的代理 API(特别是chrome.proxy.settings.set())将 PAC 设置为代理设置。该 PAC 文件将所有通信重定向到 python 脚本的代理。

mitmproxy 最大的优点之一是它还可以修改 HTTPs 通信。所以你也有:)

于 2014-10-06T21:59:24.690 回答
24

就像@Rob w 说的那样,我已经覆盖XMLHttpRequest,这是修改任何站点中的任何 XHR 请求的结果(就像透明修改代理一样工作):

var _open = XMLHttpRequest.prototype.open;
window.XMLHttpRequest.prototype.open = function (method, URL) {
    var _onreadystatechange = this.onreadystatechange,
        _this = this;

    _this.onreadystatechange = function () {
        // catch only completed 'api/search/universal' requests
        if (_this.readyState === 4 && _this.status === 200 && ~URL.indexOf('api/search/universal')) {
            try {
                //////////////////////////////////////
                // THIS IS ACTIONS FOR YOUR REQUEST //
                //             EXAMPLE:             //
                //////////////////////////////////////
                var data = JSON.parse(_this.responseText); // {"fields": ["a","b"]}

                if (data.fields) {
                    data.fields.push('c','d');
                }

                // rewrite responseText
                Object.defineProperty(_this, 'responseText', {value: JSON.stringify(data)});
                /////////////// END //////////////////
            } catch (e) {}

            console.log('Caught! :)', method, URL/*, _this.responseText*/);
        }
        // call original callback
        if (_onreadystatechange) _onreadystatechange.apply(this, arguments);
    };

    // detect any onreadystatechange changing
    Object.defineProperty(this, "onreadystatechange", {
        get: function () {
            return _onreadystatechange;
        },
        set: function (value) {
            _onreadystatechange = value;
        }
    });

    return _open.apply(_this, arguments);
};

例如,Tampermonkey 可以成功地使用此代码对任何站点进行任何修改:)

于 2018-07-30T13:12:59.343 回答
22

是的。可以使用chrome.debuggerAPI,它授予对Chrome DevTools 协议的扩展访问权限,该协议通过其网络 API支持 HTTP 拦截和修改。

此解决方案是由对 Chrome 问题 487422 的评论提出的:

对于任何想要目前可行的替代方案的人,您可以chrome.debugger在背景/事件页面中使用以附加到您想要收听的特定选项卡(或者如果可能的话,附加到所有选项卡,尚未亲自测试所有选项卡) ,然后使用调试协议的网络API。

唯一的问题是标签的视口顶部会出现通常的黄色条,除非用户在chrome://flags.

首先,将调试器附加到目标:

chrome.debugger.getTargets((targets) => {
    let target = /* Find the target. */;
    let debuggee = { targetId: target.id };

    chrome.debugger.attach(debuggee, "1.2", () => {
        // TODO
    });
});

接下来,发送Network.setRequestInterceptionEnabled命令,这将启用网络请求的拦截:

chrome.debugger.getTargets((targets) => {
    let target = /* Find the target. */;
    let debuggee = { targetId: target.id };

    chrome.debugger.attach(debuggee, "1.2", () => {
        chrome.debugger.sendCommand(debuggee, "Network.setRequestInterceptionEnabled", { enabled: true });
    });
});

Chrome 现在将开始发送Network.requestIntercepted事件。为他们添加一个监听器:

chrome.debugger.getTargets((targets) => {
    let target = /* Find the target. */;
    let debuggee = { targetId: target.id };

    chrome.debugger.attach(debuggee, "1.2", () => {
        chrome.debugger.sendCommand(debuggee, "Network.setRequestInterceptionEnabled", { enabled: true });
    });

    chrome.debugger.onEvent.addListener((source, method, params) => {
        if(source.targetId === target.id && method === "Network.requestIntercepted") {
            // TODO
        }
    });
});

在监听器中,params.request将是对应的Request对象。

发送响应Network.continueInterceptedRequest

  • 将所需 HTTP 原始响应(包括 HTTP 状态行、标头等!)的 base64 编码传递为rawResponse.
  • 作为. params.interceptionId_interceptionId

请注意,我根本没有测试过这些。

于 2017-07-20T16:59:32.773 回答
2

虽然 Safari 内置了此功能,但到目前为止我发现的 Chrome 的最佳解决方法是使用赛普拉斯的拦截功能。它干净地允许我在 Chrome 中存根 HTTP 响应。cy.intercept然后我调用cy.visit(<URL>)它,它会拦截并为访问的页面发出的特定请求提供一个存根响应。这是一个例子:

cy.intercept('GET', '/myapiendpoint', {
  statusCode: 200,
  body: {
    myexamplefield: 'Example value',
  },
})
cy.visit('http://localhost:8080/mytestpage')

注意:您可能还需要配置 Cypress以禁用某些特定于 Chrome 的安全设置。

于 2021-06-21T17:39:21.483 回答
1

Chrome 不提供任何 API 来修改响应正文。Chrome WebRequest APIDeclarativeNetRequest API都无法做到这一点。

使用桌面应用程序 - 修改任何请求类型的响应

Requestly 桌面应用程序提供了创建修改 HTTP 响应规则的功能,然后您可以在任何浏览器中使用它。这是演示视频。这是执行此操作的步骤

  1. 安装Requestly 桌面应用程序并从连接的应用程序启动您的浏览器
  2. 转到 HTTP 规则并创建修改 HTTP 响应规则
  3. 定义您的 URL 模式并定义您的自定义响应

您可以通过 3 种方式定义自定义响应

  1. 静态内容 - 您需要的固定响应
  2. Progamatic Override - 如果您需要覆盖现有服务器响应中的某些内容
  3. 从文件加载 - 在本地文件中定义您的响应并将其映射到此处。

不仅如此,您还可以使用这种方法将 HTTP 状态代码更改为 400 或 500 。

这是一个屏幕截图 - 使用 JS 代码覆盖现有响应的示例

以编程方式覆盖 HTTP 响应

使用 Requestly Chrome 扩展 - 仅针对 XHR/fetch 请求修改响应

也可以使用Requestly Chrome Extension来修改仅由 XHR/fetch 触发的 HTTP 请求的响应。这是使用 Chrome 扩展的演示视频

由于 Chrome 不提供任何 API,Requestly 会覆盖 XHR 并获取原型对象以挂钩自定义实现,您将获得您在 Requestly 响应修改规则中定义的响应。您可以在docs中阅读有关它的更多信息。

PS:我建立了请求

于 2022-02-24T10:09:51.680 回答