Как скопировать объект запроса с другим URL-адресом?
Я пишу обертку вокруг fetch
, которую я хотел бы добавить что-то в URL, прежде чем делать запрос, например. определение параметров запроса. Я не могу понять, как сделать копию данного объекта Request
с другим URL-адресом, чем оригинал. Мой код выглядит так:
// My function which tries to modify the URL of the request
function addLangParameter(request) {
const newUrl = request.url + "?lang=" + lang;
return new Request(newUrl, /* not sure what to put here */);
}
// My fetch wrapper
function myFetch(input, init) {
// Normalize the input into a Request object
return Promise.resolve(new Request(input, init))
// Call my modifier function
.then(addLangParameter)
// Make the actual request
.then(request => fetch(request));
}
Я попытался поместить исходный запрос в качестве второго аргумента в конструктор Request
, например:
function addLangParameter(request) {
const newUrl = request.url + "?lang=" + lang;
return new Request(newUrl, request);
}
который, похоже, копирует большинство атрибутов старого запроса, но, похоже, не сохраняет body
старого запроса. Например,
const request1 = new Request("/", { method: "POST", body: "test" });
const request2 = new Request("/new", request1);
request2.text().then(body => console.log(body));
Я ожидал бы log "test", но вместо этого он записывает пустую строку, потому что тело не копируется.
Нужно ли мне делать что-то более явное, чтобы правильно копировать все атрибуты, или есть хороший ярлык, который сделает что-то разумное для меня?
Я использую github/fetch polyfill, но протестировал с помощью как polyfill, так и собственной fetch
реализации в последнем Chrome.
Ответы
Ответ 1
Похоже, ваш лучший выбор - прочитать тело, используя интерфейс Body
, который выполняет Requests:
https://fetch.spec.whatwg.org/#body
Это можно сделать только асинхронно, так как основная операция "потреблять тело" всегда читается асинхронно и возвращает обещание. Что-то вроде этого должно работать:
const request = new Request('/old', { method: 'GET' });
const bodyP = request.headers.get('Content-Type') ? request.blob() : Promise.resolve(undefined);
const newRequestP =
bodyP.then((body) =>
new Request('/new', {
method: request.method,
headers: request.headers,
body: body,
referrer: request.referrer,
referrerPolicy: request.referrerPolicy,
mode: request.mode,
credentials: request.credentials,
cache: request.cache,
redirect: request.redirect,
integrity: request.integrity,
})
);
После этого newRequestP
будет обещанием, которое разрешит требуемый запрос. К счастью, выборка является асинхронной, так что ваша обертка не должна быть значительно затруднена этим.
(Примечание. Чтение тела с использованием .blob()
у запроса, у которого нет тела, похоже, возвращает объект Blob нулевой длины, но неверно указывать любое тело, даже нулевую длину, на GET или HEAD. Я считаю, что проверка того, что исходный запрос имеет Content-Type
, является точным прокси-сервером для того, имеет ли он тело, что нам действительно нужно определить.)