簡體   English   中英

如何更改請求的標頭?

[英]How to alter the headers of a Request?

是否可以更改fetch事件收到的Request object 的標頭?

兩次嘗試:

  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 object:

     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.

(另請參閱如何更改響應的標頭?

只要您設置了所有選項,就可以創建新的請求對象:

// 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
});

如果原始modenavigate ,則不能使用原始mode (這就是您收到異常的原因),並且您可能希望將重定向傳遞回瀏覽器以使其更改其 URL,而不是讓fetch處理它。

確保你沒有在 GET 請求上設置 body - fetch 不喜歡它,但瀏覽器有時會在響應來自 POST 請求的重定向時生成帶有 body 的 GET 請求。 fetch不喜歡它。

您可以基於原始請求創建一個新請求並覆蓋標頭:

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

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

您是否嘗試過類似於您提到的問題中的解決方案( 如何更改響應的標題? )?

在 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));
}

如果未來的讀者還需要刪除不可變Request / Response標頭中的鍵,並且還希望不可變標頭具有高保真度,您可以有效地克隆Header object:

const mutableHeaders = new Headers();
immutableheaders.forEach((value, key, parent) => mutableHeaders.set(key, value));

mutableHeaders.delete('content-encoding');
mutableHeaders.delete('vary');
mutableHeaders['host'] = 'example.com';
// etc.

然后您可以創建一個新的Request並傳入您的mutableHeaders

這比接受的答案更受歡迎,因為如果您需要代理Request ,您不想手動指定每個可能的 header 同時包括 Cloudflare、AWS、Azure、Google 等自定義 CDN 標頭。


背景資料

標頭在Request中不可變或只讀的原因是:

interface Request extends Body {
  readonly cache: RequestCache;
  readonly credentials: RequestCredentials;
  readonly destination: RequestDestination;
  readonly headers: Headers;
  readonly integrity: string;
    ...

Headers的接口是:

interface Headers {
    append(name: string, value: string): void;
    delete(name: string): void;
    get(name: string): string | null;
    has(name: string): boolean;
    set(name: string, value: string): void;
    forEach(callbackfn: (value: string, key: string, parent: Headers) => void, thisArg?: any): void;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM