4

Using Object methods like entries and keys produce empty arrays. JSON.stringify yields an empty object in the browser and a circular reference error in Node.js.

const request = new Request(
  'https://example.com/send',
  {
    method: 'POST',
    body: 'Hello world',
    headers: {'x-planet-origin': 'Mars'},
  },
);

const keys = Object.keys(request);
const values = Object.values(request);
const entries = Object.entries(request);
const string = JSON.stringify(request);

console.log({keys, values, entries, string, request});
jsejcksn
  • 27,667
  • 4
  • 38
  • 62

4 Answers4

1

You could try something like this:

const request = new Request(
  'https://example.com/send',
  {
    method: 'POST',
    body: 'Hello world',
    headers: {'x-planet-origin': 'Mars'},
  },
);

const str = JSON.stringify(request, ['bodyUsed',
'cache',
'credentials',
'destination','headers',
'integrity',
'isHistoryNavigation',
'keepalive',
'method',
'mode',
'redirect',
'referrer',
'referrerPolicy',
'signal',
'url']);
 
console.log(str);

//iterating dinamically
let props = [];
for(let prop in request){
props.push(prop);
}

const str2 = JSON.stringify(request, props);
 
console.log(str2);

As you could see, properties like signal result on an empty object, if you don't need that kind of properties this is a possible solution.

If you still want properties like signal you could do something like this as a second step:

const signal = JSON.stringify(request.signal, ['aborted', 'onabort']);
Emeeus
  • 5,072
  • 2
  • 25
  • 37
  • Thank you for offering a suggestion. I would like to avoid manually specifying property values, in favor of an iterative or programmatic solution. – jsejcksn Aug 11 '19 at 07:58
  • @jsejcksn As I added in the code, `for in` is a possible way to iterate over properties – Emeeus Aug 11 '19 at 14:11
0

You can use these functions to convert the stringifiable values in a Request object to values in a plain object. The first function alone will produce the described object, and the others will assist in producing a version with sorted properties.

function requestAsObject (request) {
  if (!request instanceof Request)
    throw Object.assign(
      new Error(),
      {name: 'TypeError', message: 'Argument must be a Request object'}
    );
  request = request.clone();

  function stringifiableObject (obj) {
    const filtered = {};
    for (const key in obj)
      if (['boolean', 'number', 'string'].includes(typeof obj[key]) || obj[key] === null)
        filtered[key] = obj[key];
    return filtered;
  }

  return {
    ...stringifiableObject(request),
    headers: Object.fromEntries(request.headers),
    signal: stringifiableObject(request.signal),
    // bodyText: await request.text(), // requires function to be async
  };
}

function requestAsArrayEntries (request) {
  if (!request instanceof Request)
    throw Object.assign(
      new Error(),
      {name: 'TypeError', message: 'Argument must be a Request object'}
    );
  request = request.clone();

  function entriesFromObject (obj) {
    const entries = [];
    for (const key in obj)
      if (['boolean', 'number', 'string'].includes(typeof obj[key]) || obj[key] === null)
        entries.push([key, obj[key]]);
    return entries.sort();
  }

  return [
    ...entriesFromObject(request),
    ['headers', [...request.headers].sort()],
    ['signal', entriesFromObject(request.signal)],
    // ['bodyText', await request.text()], // requires function to be async
  ].sort();
}

function objectFromNestedEntries (arrayOfEntries) {
  if (!Array.isArray(arrayOfEntries)) return arrayOfEntries;
  const obj = {};
  for (const [key, value] of arrayOfEntries) {
    obj[key] = objectFromNestedEntries(value);
  }
  return obj;
}

const request = new Request('https://example.com/send', {
  method: 'POST',
  body: 'Hello world',
  headers: {'x-planet-origin': 'Mars'},
});

const object = requestAsObject(request);
const arrayEntries = requestAsArrayEntries(request);
const sortedObject = objectFromNestedEntries(arrayEntries);

console.log({
  object,
  arrayEntries,
  sortedObject,
  objectAsString: JSON.stringify(object),
  sortedObjectAsString: JSON.stringify(sortedObject),
});

Thanks, Emeeus, for helping me think in the right direction.

jsejcksn
  • 27,667
  • 4
  • 38
  • 62
0

I needed to find a way to merge two requests together and I found that only for in loops work for Request objects.

const request = new Request(
  'https://example.com/send',
  {
    method: 'POST',
    body: 'Hello world',
    headers: {'x-planet-origin': 'Mars'},
  },
);

function getEntries(req) {
  const out = {}
  for (const key in req) { out[key] = req[key] }
  return out
}

const entries = getEntries(request);
const string = JSON.stringify(entries);

console.log({entries, string, request});
JLarky
  • 9,833
  • 5
  • 36
  • 37
-2

Try const reqrCopy = JSON.parse(JSON.stringify(request))

Then you can do all the methods you tried later on with keys and entries etc (on the copy). The request opject may be nested and therefore you want to do this to make a deep copy for those methods.

Michael
  • 4,538
  • 5
  • 31
  • 58