webRequest API: How to get the requestId of a new request?

狂风中的少年 提交于 2020-01-05 08:48:51

问题


The chrome.webRequest API has the concept of a request ID (source: Chrome webRequest documention):

Request IDs

Each request is identified by a request ID. This ID is unique within a browser session and the context of an extension. It remains constant during the the life cycle of a request and can be used to match events for the same request. Note that several HTTP requests are mapped to one web request in case of HTTP redirection or HTTP authentication.

You can use it to correlate the requests even across redirects. But how do you initially get hold off the id when start a new request with fetch or XMLHttpRequest?

So far, I have not found anything better than to use the URL of the request as a way to make the initial link between the new request and the requestId. However, if there are overlapping requests to the same resource, this is not reliable.

Questions:

  • If you make a new request (either with fetch or XMLHttpRequest), how do you reliably get access to the requestId?
  • Does the fetch API or XMLHttpRequest API allow access to the requestId?

What I want to do is to use the functionality provided by the webRequest API to modify a single request, but I want to make sure that I do not accidentally modify other pending requests.


回答1:


To the best of my knowledge, there is no direct support in the fetch or XHMLHttpRequest API. Also I'm not aware of completely reliable way to get hold of the requestId.

What I ended up doing was installing a onBeforeRequest listener, storing the requestId, and then immediately removing the listener again. For instance, it could look like this:

function makeSomeRequest(url) {

  let listener;
  const removeListener = () => {
    if (listener) {
      chrome.webRequest.onBeforeRequest.removeListener(listener);
      listener = null;
    }
  };

  let requestId;
  listener = (details) => {
    if (!requestId && urlMatches(details.url, url)) {
      requestId = details.requestId;
      removeListener();
    }
  };
  chrome.webRequest.onBeforeRequest.addListener(listener, { urls: ['<all_urls>'] });

  // install other listeners, which can then use the stored "requestId"
  // ...

  // finally, start the actual request, for instance
  const promise = fetch(url).then(doSomething);

  // and make sure to always clean up the listener
  promise.then(removeListener, removeLister);
}

It is not perfect, and matching the URL is a detail that I left open. You could simply compare whether the details.url is identical to url:

function urlMatches(url1, url2) {
  return url1 === url2;
}

Note that it is not guaranteed that you see the identical URL, for instance, if make a request against http://some.domain.test, you will see http://some.domain.test/ in your listener (see my other question about the details). Or http:// could have been replaced by https:// (here I'm not sure, but it could be because of other extensions like HTTPS Everywhere).

That is why the code above should only be seen as a sketch of the idea. It seems to work good enough in practice, as long as you do not start multiple requests to the identical URL. Still, I would be interested in learning about a better way to approach the problem.



来源:https://stackoverflow.com/questions/47331875/webrequest-api-how-to-get-the-requestid-of-a-new-request

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!