Skip to content

RedirectHandler cleans headers too aggressively #3773

@joelschou

Description

@joelschou

Bug Description

Undici explicitly supports headers passed as a Headers object, but the RedirectHandler does not account for this object type in its internal cleanRequestHeaders function.

Reproducible By

  1. Configure global dispatcher to use redirect interceptor

  2. Use undici.request to send a request with headers constructed via new Headers(...)

    import { Headers, request } from 'undici';
    
    await request( '/local/test/url', { headers: new Headers({ 'x-my-header': true }) } );
  3. Your local test server should see 'x-my-header': 'true' in the request headers

  4. Your local test server should respond with a 3xx statusCode and a location: '/local/test/alt-url' header

  5. Undici should follow the redirect and make a request to the new location

  6. Your local test server WILL NOT see 'x-my-header': 'true' in the request headers

Compare to:

  1. same as above

  2. Send the request this way instead:

    await request( '/local/test/url', { headers: { 'x-my-header': true } } );
  3. same as above

  4. same as above

  5. same as above

  6. Your local test server WILL see 'x-my-header': 'true' in the request headers

Expected Behavior

  1. Headers on the initial request should be repeated on the redirect request(s) for all supported ways to pass headers

Logs & Screenshots

I believe I've tracked this down to this logic inside cleanRequestHeaders:

// ...
} else if (headers && typeof headers === 'object') {
    for (const key of Object.keys(headers)) {
      if (!shouldRemoveHeader(key, removeContent, unknownOrigin)) {
        ret.push(key, headers[key])
      }
    }
  }
// ...

For headers constructed with new Headers(...), the typeof headers === 'object' condition will return true, but Object.keys(...) does not behave as expected on a Headers object. As a result, this for loop does not push any keys/values into ret.

Environment

  • macOS 15.0.1 (current)
  • Node v20.16.0 (LTS, but two minors behind)

Additional context

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinginterceptorsPull requests or issues related to Dispatcher Interceptors

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions