Как изменить заголовки запроса?
Можно ли изменить заголовки объекта Request
, полученного событием fetch
?
Две попытки:
-
Изменить существующие заголовки:
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
удается Failed to execute 'set' on 'Headers': Headers are immutable
.
-
Создать новый объект 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.
(См. Также Как изменить заголовки ответа?)
Ответы
Ответ 1
Создание нового объекта запроса работает до тех пор, пока вы установите все параметры:
// 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 - выборка не нравится, но браузеры иногда генерируют запросы GET с телом при ответе на перенаправления из запросов POST. fetch
не нравится.
Ответ 2
Вы пробовали с решением, аналогичным решению в вопросе, который вы упомянули (Как изменить заголовки ответа?)?
В Поваренной книге Service Worker мы вручную копируем объекты Request для их хранения в IndexedDB (https://serviceworke.rs/request-deferrer_service-worker_doc.html). Это по другой причине (мы хотели сохранить их в кеше, но мы не можем хранить запросы POST из-за 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));
}
Ответ 3
Вы можете создать новый запрос на основе исходного и переопределить заголовки:
new Request(originalRequest, {
headers: {
...originalRequest.headers,
foo: 'bar'
}
})