我正在使用WebExtension中的webRequest-API来监控客户端发出的请求。这非常有效,但是在重定向的情况下API不会按预期运行:
在这种情况下,会发出POST
,并以302 FOUND
和新位置回答。我的浏览器(Firefox 57,其他版本和其他浏览器 - 例如Chrome - 以相同的方式行事)遵循此重定向,现在向新位置发出GET
。
不幸的是,webRequest-API的行为有所不同:它跟踪第一个POST
(这是正确的)但是将第二个请求作为POST
处理,而它应该是GET
}。这是一个严重的问题,因为API跟踪了我的浏览器应该做的事情,它实际上以另一种方式做了......
可以通过以下this link to surfnet.nl并从列表中选择IDP(例如Academisch Medisch Centrum)来复制此场景(浏览器部分)。
所以,长话短说:为什么webRequest-API的行为与浏览器的行为方式不同?有没有办法让它完全跟踪浏览器的行为?
有趣的是,webRequest-API可能会正确执行,regarding the documentation:
即使规范要求方法和正文,不要改变执行重定向时,并非所有用户代理都符合此处 [浏览器显然改变了方法!],你仍然可以在那里找到有缺陷的软件。因此,建议仅将302代码设置为GET或HEAD方法的响应,并使用307临时重定向,因为在这种情况下明确禁止方法更改。 如果您希望将方法更改为GET,请使用303请参阅其他。
修改
由于历史原因,似乎浏览器会更改302
上的方法,即使它与RFC 2616相矛盾......
无论如何......问题仍然存在:我如何诱导webRequest-API采取相同的行动?
答案 0 :(得分:0)
对于任何有兴趣的人,我最终得到以下内容:
文档让我this(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
};
}
});
会发生什么?
onBeforeRequest
收到一个新请求2640
,这是一个POST。 onHeadersReceived
得到的回复表明此请求应重定向到新位置(302
)。 redirectUrl
设置为新位置来实现。 onBeforeRequest
。 webRequest-API将相同的requestId传递给它(2640
)。 对于请求生命周期,请查看插图in the docs。