aneilbaboo / replayer

Replay HTTP requests for testing Node.js / Javascript code
Apache License 2.0
33 stars 7 forks source link

replayer fails with Node.js v18? #28

Open derhuerst opened 2 years ago

derhuerst commented 2 years ago

setup

mkdir replayer-bug
cd replayer-bug
npm init --yes
npm i fetch-ponyfill@7 pinkie-promise@2
npm i replayer@2 -D
npm ls --depth 3
# replayer-bug@1.0.0 /Users/j/playground/replayer-bug
# ├─┬ fetch-ponyfill@7.1.0
# │ └─┬ node-fetch@2.6.7
# │   ├── UNMET OPTIONAL DEPENDENCY encoding@^0.1.0
# │   └─┬ whatwg-url@5.0.0
# │     ├── tr46@0.0.3
# │     └── webidl-conversions@3.0.1
# ├─┬ pinkie-promise@2.0.1
# │ └── pinkie@2.0.4
# └─┬ replayer@2.2.3
#   ├── levenshtein@1.0.2
#   └─┬ mime-types@2.1.17
#     └── mime-db@1.30.0
// index.js
'use strict'

if (process.env.VCR_MODE) {
    const replayer = require('replayer')

    replayer.configure({
        headerWhitelist: [
            // excludes User-Agent & Connection
            'Content-Type', 'Accept-Encoding', 'Accept',
        ],
        includeHeaderValues: true,
        touchHits: false,
    })
    replayer.fixtureDir(__dirname)
}

const createFetch = require('fetch-ponyfill')
const Promise = require('pinkie-promise')
const {fetch} = createFetch({Promise})

;(async () => {
    // some regular HTTP server responding with an HTML page.
    const res = await fetch('http://192.168.12.100/')
    if (!res.ok) throw new Error(res.statusText)

    const body = await res.json()
    console.log(body)
})()
.catch((err) => {
    console.error(err)
    process.exit(1)
})

expected behavior

With Node.js v16, it works as expected:

nvm use v16
# Now using Node v16.15.0 (npm 8.5.5) ~/.local/share/nvm/v16.15.0/bin/node
env VCR_MODE=record node index.js
# <!DOCTYPE 
ls -lh
# …
# -rw-r--r--   1 j  staff   5.4K May  9 15:42 5927068e5c32e04a0b4a984873cca003
# -rw-r--r--   1 j  staff   718B May  9 15:42 5927068e5c32e04a0b4a984873cca003.headers
# …
env VCR_MODE=playback node index.js
# <!DOCTYPE 

actual behavior

With Node.js v18, neither recording nor replaying works:

rm 5927068e5c32e04a0b4a984873cca003*

nvm use system
# Now using Node v18.0.0 (npm 8.6.0) /opt/homebrew/Cellar/node/18.0.0/bin/node
env VCR_MODE=record node index.js
# node:events:505
#       throw er; // Unhandled 'error' event
#       ^

# TypeError [ERR_INVALID_ARG_TYPE]: The "stream" argument must be an instance of Stream. Received an instance of EventEmitter
#     at new NodeError (node:internal/errors:372:5)
#     at eos (node:internal/streams/end-of-stream:62:11)
#     at IncomingMessage._destroy (node:_http_incoming:189:21)
#     at _destroy (node:internal/streams/destroy:109:10)
#     at IncomingMessage.destroy (node:internal/streams/destroy:71:5)
#     at endReadableNT (node:internal/streams/readable:1360:16)
#     at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
# Emitted 'error' event on IncomingMessage instance at:
#     at emitErrorNT (node:internal/streams/destroy:151:8)
#     at emitErrorCloseNT (node:internal/streams/destroy:116:3)
#     at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
#   code: 'ERR_INVALID_ARG_TYPE'
# }

# Node.js v18.0.0
ls -lh
# …
# -rw-r--r--   1 j  staff   5.4K May  9 15:44 5927068e5c32e04a0b4a984873cca003
# -rw-r--r--   1 j  staff   718B May  9 15:44 5927068e5c32e04a0b4a984873cca003.headers
# …
env VCR_MODE=playback node index.js
# node:events:505
#       throw er; // Unhandled 'error' event
#       ^

# TypeError [ERR_INVALID_ARG_TYPE]: The "stream" argument must be an instance of Stream. Received an instance of EventEmitter
#     at new NodeError (node:internal/errors:372:5)
#     at eos (node:internal/streams/end-of-stream:62:11)
#     at IncomingMessage._destroy (node:_http_incoming:189:21)
#     at _destroy (node:internal/streams/destroy:109:10)
#     at IncomingMessage.destroy (node:internal/streams/destroy:71:5)
#     at endReadableNT (node:internal/streams/readable:1360:16)
#     at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
# Emitted 'error' event on IncomingMessage instance at:
#     at emitErrorNT (node:internal/streams/destroy:151:8)
#     at emitErrorCloseNT (node:internal/streams/destroy:116:3)
#     at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
#   code: 'ERR_INVALID_ARG_TYPE'
# }

# Node.js v18.0.0

more info

It seems that it fails because node-fetch calls res.pipe(new PassThrough()):

Screenshot 2022-05-09 at 18 17 02
aneilbaboo commented 2 years ago

Hi - sorry for the trouble. I am no longer maintaining this project. You might want to try out something like Polly.js: https://netflix.github.io/pollyjs/#/

derhuerst commented 2 years ago

Alright, thanks!