如何复制具有不同 URL 的 Request 对象?
How do I copy a Request object with a different URL?
我正在围绕 fetch
编写包装器,我想在发出请求之前向 URL 添加一些内容,例如识别查询参数。我无法弄清楚如何使用与原始 URL 不同的给定 Request
对象制作副本。我的代码如下所示:
// 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));
我希望记录 "test",但它记录的是空字符串,因为没有复制正文。
我是否需要做一些更明确的事情来正确复制所有属性,或者是否有一个不错的快捷方式可以为我做一些合理的事情?
我正在使用 github/fetch polyfill,但在最新的 Chrome.
中测试了 polyfill 和本机 fetch
实现
看起来你最好的选择是使用 Requests 实现的 Body
接口来读取正文:
https://fetch.spec.whatwg.org/#body
这只能异步完成,因为底层 "consume body" 操作总是异步读取并且 return 是一个承诺。这样的事情应该有效:
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
将是一个解决您想要的请求的承诺。幸运的是,fetch 无论如何都是异步的,因此您的包装器不应因此而受到严重阻碍。
(注意:使用 .blob()
从没有主体的请求中读取主体似乎是 return 一个 zero-length Blob 对象,但指定任何主体都是不正确的,即使是 zero-length 一个,在 GET 或 HEAD 请求上。我相信检查原始请求是否设置了 Content-Type
是它是否有主体的准确代理,这是我们真正需要的确定。)
我正在围绕 fetch
编写包装器,我想在发出请求之前向 URL 添加一些内容,例如识别查询参数。我无法弄清楚如何使用与原始 URL 不同的给定 Request
对象制作副本。我的代码如下所示:
// 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));
我希望记录 "test",但它记录的是空字符串,因为没有复制正文。
我是否需要做一些更明确的事情来正确复制所有属性,或者是否有一个不错的快捷方式可以为我做一些合理的事情?
我正在使用 github/fetch polyfill,但在最新的 Chrome.
中测试了 polyfill 和本机fetch
实现
看起来你最好的选择是使用 Requests 实现的 Body
接口来读取正文:
https://fetch.spec.whatwg.org/#body
这只能异步完成,因为底层 "consume body" 操作总是异步读取并且 return 是一个承诺。这样的事情应该有效:
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
将是一个解决您想要的请求的承诺。幸运的是,fetch 无论如何都是异步的,因此您的包装器不应因此而受到严重阻碍。
(注意:使用 .blob()
从没有主体的请求中读取主体似乎是 return 一个 zero-length Blob 对象,但指定任何主体都是不正确的,即使是 zero-length 一个,在 GET 或 HEAD 请求上。我相信检查原始请求是否设置了 Content-Type
是它是否有主体的准确代理,这是我们真正需要的确定。)