node-twitter-api-v2 icon indicating copy to clipboard operation
node-twitter-api-v2 copied to clipboard

[bug] TypeError: Cannot read properties of undefined (reading 'Z_SYNC_FLUSH')

Open Eversmile12 opened this issue 2 years ago • 1 comments

Describe the bug Context:

  • I'm building a Chrome extension
  • The code fetching the tweet is in a background page handled through Plasmo
  • I'm using the app login auth through single bearer
  • When fetching single tweet through ID, both v1 and v2, I get the following error:

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'Z_SYNC_FLUSH') at RequestHandlerHelper.getResponseDataStream (request-handler.helper.js:99:39) at RequestHandlerHelper.classicResponseHandler (request-handler.helper.js:196:33) at A.emit (https.js:1:3775) at A._connect (https.js:1:81698) at https.js:1:80279

at request-handler.helper.js there's the getResponseDataStream() that looks like its converting response from the tw API into gzip getResponseDataStream(res) { if (this.isCompressionDisabled()) { return res; } const contentEncoding = (res.headers['content-encoding'] || 'identity').trim().toLowerCase(); if (contentEncoding === 'br') { const brotli = zlib.createBrotliDecompress({ flush: zlib.constants.BROTLI_OPERATION_FLUSH, finishFlush: zlib.constants.BROTLI_OPERATION_FLUSH, }); res.pipe(brotli); return brotli; } if (contentEncoding === 'gzip') { const gunzip = zlib.createGunzip({ flush: zlib.constants.Z_SYNC_FLUSH, finishFlush: zlib.constants.Z_SYNC_FLUSH, }); res.pipe(gunzip); return gunzip; } if (contentEncoding === 'deflate') { const inflate = zlib.createInflate({ flush: zlib.constants.Z_SYNC_FLUSH <----- **ERROR**, finishFlush: zlib.constants.Z_SYNC_FLUSH <----- **ERROR**, }); res.pipe(inflate); return inflate; } return res; }

Looks like the zlib Z_SYNC_FLUSH constant isn't there. 

I can see the tweet coming through the request.

To Reproduce Please indicate all steps that lead to this bug:

  1. Create a new application using Plasmo - plasmo.com
  2. In a content script send a message to a background page
  3. Fetch the Tweet in the background page

Or clone the following repo and:

  • run pnpm install
  • remember to add bearer to .env or substitute variable in twitterHandler.ts
  • run pnpm dev
  • open the project directory and locate the "build" folder
  • activate developer mode on chrome://extensions
  • drag and drop the dev folder on chrome://extensions
  • go on Twitter
  • click on a tweet
  • click on the right corner button - tweet

You'll see the error logged in the background worker console (accessible through chrome://extensions) https://github.com/Eversmile12/lenshare

Expected behavior It should fetch the tweet

Version

  • Node.js v16.16.0
  • Lib 1.14.2
  • OS mac

Eversmile12 avatar Mar 16 '23 16:03 Eversmile12

Ah, here's the catch!

Actually a couple.

1 - Where is z_sync_flush?

z_sync_flush, disappeared, couldn't find it in the latest version of zlib - setting both the "flush" and "finishFlush" properties to "2" - value of the z_sync_flush will solve the issue.

2- Looks like Twitter is sending back a response with a content-encoding header set to "gzip" whereas the payload is actually plain, simple JSON.

The library is seeing the content-encoding header and tries to inflate it, finding the wrong content header. Solution - try to catch and revert to sending back only the res if the header is wrong.

Plus, there are a bunch of import types that weren't specified, hope you appreciate me adding them! - linted the code.

Sending pr now, two separate for both.

Eversmile12 avatar Mar 16 '23 18:03 Eversmile12