Skip to content

Support sending raw headers #2103

Closed as not planned
Closed as not planned
@pimterry

Description

@pimterry

Is there an existing issue for this?

  • I've searched for any related issues and avoided creating a duplicate issue.

Description

(This is not a bug, it's a feature request, but there's no available template for that in https://github.com/websockets/ws/issues/new).

It would be helpful to be able to set raw headers for a WS client connection. This is notably useful because many services now use bot detection (e.g. many services that use Cloudflare/Akamai/etc) which blocks requests from all non-browser clients, detecting them both by TLS fingerprint and by fingerprinting details of HTTP connections, e.g. the header order, and the casing of case-insensitive header names.

Node itself already supports this in various HTTP APIs (e.g.) by accepting a flat array of [key, value, key, value] headers for the headers option (in addition to the object header format) which are then sent as-is without any further transformation to handle duplicates or header name casing. Headers are similarly exposed in the same raw format by the request.rawHeaders property.

Apparently this is also helpful for performance when proxying, which was Node's original justification for supporting this, allowing proxies to receive and forward the raw headers with no processing necessary.

It would be useful if WS also supported this. Right now WS assumes that opts.headers is always an object, e.g. here:

ws/lib/websocket.js

Lines 715 to 721 in ea76193

opts.headers = {
...opts.headers,
'Sec-WebSocket-Version': opts.protocolVersion,
'Sec-WebSocket-Key': key,
Connection: 'Upgrade',
Upgrade: 'websocket'
};

ws version

All (feature request)

Node.js Version

All (feature request)

System

All (feature request)

Expected result

It should be possible to set raw headers like so:

new WebSocket(wsUrl, {
    headers: ['my-header', 'my-value', 'Another-Header', 'another-value', 'my-header', 'dupe-value']
});

and have the upstream request made with all headers (including the duplicate) in the given order, and with the header casing preserved as provided.

Actual result

It's not possible to provide raw header data.

Attachments

I'm happy to investigate this myself and open a PR for it - I'm mainly just looking for confirmation that this is a feature you're open to.

I think because changing this would imply tracking headers internally everywhere in raw format, this could complicate internal header handling slightly, but I think it's manageable without much impact. It could also subtly change the format of headers sent upstream in the existing object header option case (e.g. the best approach would imply preserving the user-specified case from object header keys, instead of lowercasing automatically as now). There should be no changes though that would affect the normal semantics of the request, and I expect that's acceptable to everybody who isn't already concerned with sending raw headers like this anyway.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions