如何更改请求的标头?

IT技术 javascript service-worker
2021-03-15 02:08:18

是否可以更改事件Request接收到对象的标头fetch

两次尝试:

  1. 修改现有标题:

    self.addEventListener('fetch', function (event) {
      event.request.headers.set("foo", "bar");
      event.respondWith(fetch(event.request));
    });
    

    失败Failed to execute 'set' on 'Headers': Headers are immutable

  2. 创建新Request对象:

    self.addEventListener('fetch', function (event) {
      var req = new Request(event.request, {
        headers: { "foo": "bar" }
      });
      event.respondWith(fetch(req));
    });
    

    失败 Failed to construct 'Request': Cannot construct a Request with a Request whose mode is 'navigate' and a non-empty RequestInit.

(另请参阅如何更改响应的标头?

3个回答

只要您设置了所有选项,就可以创建新的请求对象:

// request is event.request sent by browser here 
var req = new Request(request.url, {
    method: request.method,
    headers: request.headers,
    mode: 'same-origin', // need to set this properly
    credentials: request.credentials,
    redirect: 'manual'   // let browser handle redirects
});

mode如果是navigate则不能使用原始文件(这就是您收到异常的原因),并且您可能希望将重定向传递回浏览器以使其更改其 URL 而不是让它fetch处理它。

确保你没有在 GET 请求上设置 body - fetch 不喜欢它,但浏览器有时会在响应来自 POST 请求的重定向时生成带有 body 的 GET 请求。fetch不喜欢。

在邮寄的情况下,请求正文呢?
2021-04-24 02:08:18
你知道为什么 a modeofnavigate会是一个问题吗?
2021-05-08 02:08:18
fetch.spec.whatwg.org/#dom-request 的第 12.1:“如果请求的模式是“导航”,则抛出一个类型错误。”。
2021-05-15 02:08:18

您可以基于原始请求创建一个新请求并覆盖标头:

new Request(originalRequest, {
  headers: {
    ...originalRequest.headers,
    foo: 'bar'
  }
})

另见:https : //developer.mozilla.org/en-US/docs/Web/API/Request/Request

正是我所需要的!谢谢。我快疯了。
2021-04-27 02:08:18
您应该添加一些上下文……这个解决方案更胜一筹。您可以在 new Request 处抛出 event.request 并使不可变标头“可变”:D 然后您可以调整标头以处理新创建的请求。在 fetch 上下文中,这只是 3 行代码:)。对我来说也似乎非常健壮和错误证明。
2021-05-14 02:08:18

您是否尝试过类似于您提到的问题中的解决方案(如何更改响应的标题?)?

在 Service Worker Cookbook 中,我们手动复制 Request 对象以将它们存储在 IndexedDB ( https://serviceworke.rs/request-deferrer_service-worker_doc.html ) 中。这是出于不同的原因(我们想将它们存储在 Cache 中,但由于https://github.com/slightlyoff/ServiceWorker/issues/693我们无法存储 POST 请求),但它应该适用于您也想做。

// Serialize is a little bit convolved due to headers is not a simple object.
function serialize(request) {
  var headers = {};
  // `for(... of ...)` is ES6 notation but current browsers supporting SW, support this
  // notation as well and this is the only way of retrieving all the headers.
  for (var entry of request.headers.entries()) {
    headers[entry[0]] = entry[1];
  }
  var serialized = {
    url: request.url,
    headers: headers,
    method: request.method,
    mode: request.mode,
    credentials: request.credentials,
    cache: request.cache,
    redirect: request.redirect,
    referrer: request.referrer
  };



  // Only if method is not `GET` or `HEAD` is the request allowed to have body.
  if (request.method !== 'GET' && request.method !== 'HEAD') {
    return request.clone().text().then(function(body) {
      serialized.body = body;
      return Promise.resolve(serialized);
    });
  }
  return Promise.resolve(serialized);
}

// Compared, deserialize is pretty simple.
function deserialize(data) {
  return Promise.resolve(new Request(data.url, data));
}