ladjs / superagent

Ajax for Node.js and browsers (JS HTTP client). Maintained for @forwardemail, @ladjs, @spamscanner, @breejs, @cabinjs, and @lassjs.
https://ladjs.github.io/superagent/
MIT License
16.58k stars 1.33k forks source link

[fix] Brotli support #1811

Closed yigaldviri closed 2 weeks ago

yigaldviri commented 1 month ago

Describe the bug

Node.js version: Node 14, 16, 18, 20

OS version: Mac Ventura 3.0.1

Description: It seems like its not possible to receive a response body when the content is compressed using Brotli compression.

Actual behavior

SyntaxError: Unexpected token in JSON at position 0 since the body isn't decompressed

Expected behavior

Body decompressed from Brotli and JSON is returned

Code to reproduce

I tried this simple code:

const superagent = require('superagent');

superagent
  .get('http://httpbin.org/brotli')
  .set('Accept-Encoding', 'br, gzip, deflate')
  .then(response => {
    console.log('Response Headers:', response.headers);
    console.log('Response:', response.text);
  })
  .catch(error => {
    console.error('Failed getting Brotli response');
    console.error('Error:', error);
  });

And got SyntaxError: Unexpected token in JSON at position 0 since the body isn't decompressed

When I tried to manually decompress it like that:

const brotli = require('brotli');
const superagent = require('superagent');

superagent
  .get('http://httpbin.org/brotli')
  .set('Accept-Encoding', 'br, gzip, deflate')
  .responseType('arraybuffer') // Get the response as a buffer
  .then(response => {
    console.log('Response Headers:', response.headers);
    const contentEncoding = response.headers['content-encoding'];

    const decompressedData = brotli.decompress(response.body);

    const responseText = new TextDecoder().decode(decompressedData);
    console.log('Response Data:', responseText);
  })
  .catch(error => {
    console.error('Failed getting Brotli response');
    console.error('Error:', error);
  });

It worked and I got the proper result:

Response Headers: {
  date: 'Sun, 14 Jul 2024 06:21:12 GMT',
  'content-type': 'application/json',
  'content-length': '173',
  connection: 'close',
  server: 'gunicorn/19.9.0',
  'content-encoding': 'br',
  'access-control-allow-origin': '*',
  'access-control-allow-credentials': 'true'
}
Response Data: {
  "brotli": true, 
  "headers": {
    "Accept-Encoding": "br, gzip, deflate", 
    "Host": "httpbin.org", 
  }, 
  "method": "GET", 
}

I tried using node-fetch and axios and it worked without a need to manually intercept it and Im guessing that behind the scenes you are using Node's http module that have the zlib module that handles gzip and etc... so what am I missing here?

Checklist

titanism commented 2 weeks ago

Resolved per https://github.com/ladjs/superagent/pull/1812

v10.0.0 is released to npm, can you please try it out and let us know if it works OK? 🙏

Thank you for your contribution 🎉

Ref: https://github.com/ladjs/superagent/releases/tag/v10.0.0