【问题标题】:How do I copy a Request object with a different URL?如何复制具有不同 URL 的请求对象?
【发布时间】:2016-04-10 23:11:06
【问题描述】:

我正在围绕 fetch 编写一个包装器,我想在发出请求之前向 URL 添加一些内容,例如识别查询参数。我不知道如何使用与原始 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));

我希望记录“测试”,但它记录的是空字符串,因为正文没有被复制。

我需要做一些更明确的事情来正确复制所有属性,还是有一个不错的快捷方式可以为我做一些合理的事情?

我正在使用 github/fetch polyfill,但已经在最新的 Chrome 中测试了 polyfill 和原生 fetch 实现。

【问题讨论】:

  • 不显示伪代码:显示真实代码。
  • @Mike'Pomax'Kamermans 我添加了实际代码。我认为这使理解实际问题变得更加困难,也许会有所帮助。
  • 通过在代码本身中显示您对 Request 对象的使用,您的新代码实际上使您的问题一目了然。

标签: javascript fetch-api


【解决方案1】:

看起来最好的办法是使用 Requests 实现的 Body 接口读取正文:

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 将是一个可以解决您想要的请求的承诺。幸运的是,无论如何 fetch 都是异步的,所以你的包装器不应该受到很大的阻碍。

(注意:使用.blob() 从没有正文的请求中读取正文似乎会返回零长度的 Blob 对象,但在GET 或 HEAD 请求。我相信检查原始请求是否设置了Content-Type 是它是否具有主体的准确代理,这是我们真正需要确定的。)

【讨论】:

  • 看起来这在 github/fetch polyfill 中目前不起作用(它没有适当地设置 Content-Type 标头),但这在 Chrome 中效果很好。谢谢!
  • 正确的body 赋值following MDN† 可能是const body = ['GET', 'HEAD'].includes(r.method) ? undefined : await r.blob()。 † MDN 声明:“使用 GET 或 HEAD 方法的请求不能有正文。”
猜你喜欢
  • 2013-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 2013-05-12
  • 2021-03-14
  • 2016-05-13
相关资源
最近更新 更多