如何更改请求的 headers?
How to alter the headers of a Request?
是否可以更改 Request
object that is received by the fetch
事件的 headers?
两次尝试:
修改已有的headers:
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
。
新建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.
(另见 )
您是否尝试过类似于您提到的问题 () 中的解决方案?
在 Service Worker Cookbook 中,我们手动复制 Request 对象以将它们存储在 IndexedDB (https://serviceworke.rs/request-deferrer_service-worker_doc.html). It's for a different reason (we wanted to store them in a Cache, but we can't store POST requests because of https://github.com/slightlyoff/ServiceWorker/issues/693) 中,但它也应该适用于您想要执行的操作。
// 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 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
不喜欢
您可以根据原始请求创建新请求并覆盖 headers:
new Request(originalRequest, {
headers: {
...originalRequest.headers,
foo: 'bar'
}
})
另请参阅:https://developer.mozilla.org/en-US/docs/Web/API/Request/Request
如果未来的读者还需要 删除 不可变 Request
/Response
header 中的键并且还想要高保真度对于不可变的 headers,您可以有效地克隆 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
,您不想在包括 Cloudflare、AWS、Azure 时手动指定每个可能的 header , Google, 等自定义CDN headers.
背景信息
header 不可变或 Request
中的 read-only 的原因是:
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;
}
是否可以更改 Request
object that is received by the fetch
事件的 headers?
两次尝试:
修改已有的headers:
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
。新建
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.
(另见
您是否尝试过类似于您提到的问题 (
在 Service Worker Cookbook 中,我们手动复制 Request 对象以将它们存储在 IndexedDB (https://serviceworke.rs/request-deferrer_service-worker_doc.html). It's for a different reason (we wanted to store them in a Cache, but we can't store POST requests because of https://github.com/slightlyoff/ServiceWorker/issues/693) 中,但它也应该适用于您想要执行的操作。
// 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 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
不喜欢
您可以根据原始请求创建新请求并覆盖 headers:
new Request(originalRequest, {
headers: {
...originalRequest.headers,
foo: 'bar'
}
})
另请参阅:https://developer.mozilla.org/en-US/docs/Web/API/Request/Request
如果未来的读者还需要 删除 不可变 Request
/Response
header 中的键并且还想要高保真度对于不可变的 headers,您可以有效地克隆 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
,您不想在包括 Cloudflare、AWS、Azure 时手动指定每个可能的 header , Google, 等自定义CDN headers.
背景信息
header 不可变或 Request
中的 read-only 的原因是:
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;
}