Skip to content

decompressResponse changes the type of the response object #2389

@barjin

Description

@barjin

A response with enabled decompression is a prototype-child of a PassThrough stream, but without the decompression, it's Node's IncomingMessage.

This happens here in got:

response = decompressResponse(response);

Why is it a problem

  1. We get different response objects based on the server's decision (compression/no compression). This is not very clear to anyone who needs to debug this.
  2. The PassThrough stream has some own properties hanging from it (e.g. the headers getter), but the IncomingMessage response only inherits those from the IncomingMessage prototype. This means that { ...passThroughResponse }.headers exists, but { ...incomingMessageResponse }.headers is undefined. See 1. - this only depends on the server's decision, so it gets really confusing.

Minimal reproduction scenario:

// compresedResponse is a PassThrough stream (because of the decompression)
const compressedResponse = await got('http://httpbin.org/gzip');
const { headers: gzipHeaders } = { ...compressedResponse };

// uncompressedResponse is an IncomingMessage (native Node.js response object)
const uncompressedResponse = await got('http://httpbin.org/html');
const { headers: htmlHeaders } = { ...uncompressedResponse };

console.log(`gzip response headers:`, gzipHeaders);
console.log(`html response headers:`, htmlHeaders);

results in

gzip response headers: {
  date: 'Thu, 21 Nov 2024 13:14:39 GMT',
  'content-type': 'application/json',
  'content-length': '236',
  connection: 'keep-alive',
  server: 'gunicorn/19.9.0',
  'content-encoding': 'gzip',
  'access-control-allow-origin': '*',
  'access-control-allow-credentials': 'true'
}
html response headers: undefined

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions