Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions core/packages/teeny-request/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,12 @@ function teenyRequest(
teenyRequest.stats.requestFinished();
responseStream = res.body;

// node-fetch v3's internal pipeline listeners plus the wiring below
// legitimately exceed the default limit of 10, warning on every
// streamed response
// see: https://github.com/googleapis/google-cloud-node/issues/9185
responseStream.setMaxListeners(0);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Calling setMaxListeners directly on responseStream can throw a TypeError if responseStream is null/undefined, or if it is a non-Node stream (such as a Web ReadableStream in isomorphic/browser environments or certain mock streams) that does not implement setMaxListeners.

To prevent potential runtime crashes, we should defensively check if responseStream is defined and if setMaxListeners is a function before calling it.

        if (responseStream && typeof responseStream.setMaxListeners === 'function') {
          responseStream.setMaxListeners(0);
        }


responseStream.on('error', (err: Error) => {
requestStream.emit('error', err);
});
Expand Down
12 changes: 12 additions & 0 deletions core/packages/teeny-request/test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,18 @@ describe('teeny', () => {
});
});

// see: https://github.com/googleapis/google-cloud-node/issues/9185
it('should remove the listener limit on the fetch response stream', done => {
const scope = mockJson();
const stream = teenyRequest({uri}).on('error', done);
stream.on('response', res => {
assert.strictEqual(res.body.getMaxListeners(), 0);
scope.done();
done();
});
stream.resume();
});

it('should expose TeenyStatistics instance', () => {
assert.ok(teenyRequest.stats instanceof TeenyStatistics);
});
Expand Down
Loading