Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I copy a Request object with a different URL?

I'm writing a wrapper around fetch that I would like to add something to the URL before making the request e.g. identifying query parameters. I can't figure out how to make a copy of a given a Request object with a different URL than the original. My code looks like:

// 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));
}

I tried putting the original request as the second arguent to the Request constructor, like so:

function addLangParameter(request) {
    const newUrl = request.url + "?lang=" + lang;
    return new Request(newUrl, request);
}

which seems to copy most of the attributes of the old request but doesn't seem to preserve the body of the old request. For example,

const request1 = new Request("/", { method: "POST", body: "test" });
const request2 = new Request("/new", request1);
request2.text().then(body => console.log(body));

I would expect to log "test", but instead it logs the empty string, because the body is not copied over.

Do I need to do something more explicit to copy all of the attributes correctly, or is there a nice shortcut that will do something reasonable for me?

I'm using the github/fetch polyfill, but have tested with both the polyfill and the native fetch implementation in the lastest Chrome.

like image 875
Xymostech Avatar asked Jan 06 '16 18:01

Xymostech


People also ask

What is request clone?

clone() The clone() method of the Request interface creates a copy of the current Request object. Like the underlying ReadableStream.

What is clone in js?

Cloning. Cloning in javascript is nothing but copying an object properties to another object so as to avoid creation of an object that already exists. There are a few ways to clone a javascript object. 1) Iterating through each property and copy them to a new object. 2) Using JSON method.

What is the request object?

The request object is the main entry point for an application to issue a request to the Library - all operations on a URL must use a Request object. The request object is application independent in that both servers and clients use the same Request class.


1 Answers

It looks like your best bet is to read the body using the Body interface that Requests implement:

https://fetch.spec.whatwg.org/#body

This can only be done asynchronously since the underlying "consume body" operation always reads asynchronously and returns a promise. Something like this should work:

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,
    })
  );

After doing that, newRequestP will be a promise that resolves to the request you want. Luckily, fetch is asynchronous anyway so your wrapper shouldn't be significantly hampered by this.

(Note: Reading the body using .blob() off of a request that does not have a body seems to return a zero-length Blob object, but it's incorrect to specify any body, even a zero-length one, on a GET or HEAD request. I believe that checking if the original request had Content-Type set is an accurate proxy for whether it has a body, which is what we really need to determine.)

like image 82
Sophie Alpert Avatar answered Oct 11 '22 13:10

Sophie Alpert