Skip to content

[node-http-handler] 100 continue promise prevents node process exit #4769

Closed
@dominique-pfister

Description

@dominique-pfister

Checkboxes for prior research

Describe the bug

After updating to @aws-sdk/node-http-handler version 3.341.0, we suddenly experience test runs that hang for a couple of seconds, after all tests have been executed.

SDK version number

@aws-sdk/node-http-handler@3.341.0

Which JavaScript Runtime is this issue in?

Node.js

Details of the browser/Node.js/ReactNative version

v18.16.0

Reproduction Steps

import assert from 'assert';
import nock from 'nock';
import { HttpRequest } from '@aws-sdk/protocol-http';
import { NodeHttpHandler } from '@aws-sdk/node-http-handler';

describe('Test exposing setTimeout blocking test exit', () => {
  it('can handle expect 100-continue', async () => {
    nock('http://localhost:8080/')
      .put('/')
      .reply(201);
    const body = Buffer.from('test');
    const nodeHttpHandler = new NodeHttpHandler({ requestTimeout: 15000 });
    const { response } = await nodeHttpHandler.handle(
      new HttpRequest({
        hostname: 'localhost',
        method: 'PUT',
        port: 8080,
        protocol: 'http:',
        path: '/',
        headers: {
          Expect: '100-continue',
        },
        body,
      }),
      {},
    );
    assert.strictEqual(response.statusCode, 201);
  });
});

Observed Behavior

Executing that test with $ npx mocha node-http-handler.test.js shows a successful test run, but the node process hangs for the number of milliseconds specified in the requestTimeout above. Same happens when 100 Continue is actually returned by the server.

Expected Behavior

After the test has executed, the node process should exit.

Possible Solution

In

one could save the setTimeout return value (a timeout handle) and clear the timeout after the continue event has been received:

if (expect === "100-continue") {
    let timeout;
    await Promise.race<void>([
      new Promise((resolve) => {
        timeout = setTimeout(resolve, Math.max(MIN_WAIT_TIME, maxContinueTimeoutMs));
      }),
      new Promise((resolve) => {
        httpRequest.on("continue", () => {
          if (timeout) {
            clearTimeout(timeout);
          }
          resolve();
        });
      }),
    ]);
  }

Additional Information/Context

No response

Metadata

Metadata

Assignees

Labels

bugThis issue is a bug.p2This is a standard priority issue

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions