nodejs / help

:sparkles: Need help with Node.js? File an Issue here. :rocket:
1.44k stars 276 forks source link

Fetch not working as expected for http status 421 #4345

Closed bdemann closed 4 months ago

bdemann commented 4 months ago

Details

If the client sends a request with a body of length greater than 0 and the server responds with a 421 status then node.js fetch will fail with the following error

Error: TypeError: fetch failed
    at node:internal/deps/undici/undici:12344:11
    at async fetch421Endpoint (fourZeroSeven/fetch.js:38:22) {
  cause: RequestContentLengthMismatchError: Request body length does not match content-length header
      at AsyncWriter.end (node:internal/deps/undici/undici:9742:19)
      at writeIterable (node:internal/deps/undici/undici:9646:16)
      at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
    code: 'UND_ERR_REQ_CONTENT_LENGTH_MISMATCH'
  }
}

Sending the same request with cURL or fetch in Firefox or Chrome results in the expected response with a 421 status.

Because it only happens with request bodies of length 1 or greater, GET requests always work as expected.

I have more details and a simple reproduction of the error in this repo https://github.com/demergent-labs/fourZeroSeven

Node.js version

I have tried on the following node version: v18.18.0 and v21.6.1

Example code

Here is the endpoint on the server

// Endpoint for 421 response
app.post('/421', (req, res) => {
  res.status(421).send('This is a 421 Misdirected Request response.');
});

Here is the fetch request

async function fetch421Endpoint() {
  try {
    const response = await fetch('http://localhost:3000/421', {
      method: 'POST',
      body: new Uint8Array(Buffer.from('helloworld', 'utf-8'))
    });
    if (response.status === 421) {
      const data = await response.text();
      console.log('421 endpoint response:', data);
    } else {
      console.log('421 endpoint didn\'t return with 421 status');
      console.error('Error:', response.status, response.statusText);
    }
  } catch (error) {
    console.log('421 endpoint failed');
    console.error('Error:', error);
  }
}

For more details see https://github.com/demergent-labs/fourZeroSeven

Operating system

Ubuntu 23.10

Scope

runtime

Module and version

fetch

VoltrexKeyva commented 4 months ago

The global fetch() API is provided by Undici, please open an issue there instead.

bdemann commented 4 months ago

Thank you for the direction, here is that issue https://github.com/nodejs/undici/issues/2898