0

我在 WebExtension 中使用webRequest-API来监视客户端发出的请求。这工作得很好,但是在重定向的情况下,API 的行为并不像预期的那样:

在这种情况下POST,发出 a 并以 a302 FOUND和一个新位置作为回答。GET我的浏览器(Firefox 57、其他版本和其他浏览器 - 例如 Chrome - 以相同的方式运行)遵循此重定向,现在向新位置发出 a 。

在此处输入图像描述

不幸的是,webRequest-API 的行为不同:它跟踪第一个POST请求(这是正确的),但也将第二个请求作为 a 处理POST,而它应该是 a GET。这是一个严重的问题,因为 API 跟踪了我的浏览器应该做的事情,而实际上它以另一种方式做了......

这个场景(浏览器部分)可以通过这个链接复制到 surfnet.nl并从列表中选择一个 IDP(例如 Academisch Medisch Centrum)。

所以,长话短说:为什么 webRequest-API 的行为与浏览器的行为方式不同?有没有办法让它准确地跟踪浏览器的操作?

有趣的是,关于文档,webRequest-API 可能会正确执行:

即使规范要求方法和主体在执行重定向时不被更改,也不是所有的用户代理都符合这里[浏览器显然改变了方法!],您仍然可以在那里找到有缺陷的软件。因此,建议仅将 302 代码设置为 GET 或 HEAD 方法的响应,并改用 307 临时重定向,因为在这种情况下明确禁止更改方法。如果您希望将使用的方法更改为 GET,请改用 303 See Other。


编辑: 似乎浏览器302由于历史原因改变了方法,即使它与RFC 2616相矛盾......

无论如何......问题仍然存在:我怎样才能诱导 webRequest-API 以同样的方式行事?

4

1 回答 1

0

对于任何有兴趣的人,我最终得到以下结果:

文档让我这样做redirectUrl):

[...] 重定向操作启动的重定向使用原始请求方法进行重定向,但有一个例外:如果重定向是在 onHeadersReceived 阶段启动的,则将使用 GET 方法发出重定向。[...]

尽管上面的陈述给了我一些希望,但method那个重定向的请求仍然被标记为 POST ......

所以我将代码更新为大致如下:

// Keep track of all requests issued so far and their responses
var httpRequests = [];

// Redirected requests come in with their originating parents' ID
browser.webRequest.onBeforeRequest.addListener(request => {
    // Check if the request is a redirect
    var isRedirected = function(requestId) {
        var parentRequest = httpRequests.find(r => r.req.requestId === requestId);
        if (parentRequest != null && parentRequest.res != null && parentRequest.res.statusCode === 302) {
            return true;
        }
        return false;
    };

    // The webRequest-API seems to keep the HTTP verbs which is correct in resepct to RFC 2616 but
    // differs from a typical browser behaviour which will usually change the POST to a GET. So do we here...
    if (request.method === 'POST' && isRedirected(request.requestId)) {
        console.log(`Redirected 302-request '${request.requestId}' is a POST but is here changed to a GET to conform to browser behaviour...`);
        request.method = 'GET';
    }

    // Store the request
    var entry = {
        id: id,
        req: request
    };
    httpRequests.push(entry);
});

browser.webRequest.onHeadersReceived.addListener(response => {
    // Store the response alongside the request
    var entry = httpRequests.find(req => req.id === response.requestId);
    entry.res = response;

    // If it turns out that a request should be redirected...
    if (response.statusCode === 302) {
        var location = response.responseHeaders.find(header => header.name.toLowerCase() === "location");
        console.log(`Redirecting request '${id}' to new location '${location.value}'...`);

        // The new location is set as redirectUrl, which results in a new invocation of onBeforeRequest with
        // the current requestId
        return {
            redirectUrl: location.value
        };
    }
});

怎么了?

  1. SayonBeforeRequest收到2640一个 POST 的新请求。
  2. onHeadersReceived获得表示该请求应重定向到新位置的响应 ( 302)。
  3. 上面的代码通过将 设置redirectUrl为该新位置来实现。
  4. 然后onBeforeRequest再次触发。webRequest-API 将相同的 requestId 传递给它 ( 2640)。
  5. 代码检查此请求是否有父级,在本例中为真。
  6. 然后将该方法(仍然是 POST)修改为 GET。

对于请求生命周期,请查看文档中的插图。

于 2018-02-24T19:03:15.277 回答