Description
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:
Lines 715 to 721 in ea76193
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.