HTTP/2 over unix domain sockets returns `ERR_SSL_WRONG_VERSION_NUMBER`
Bug Description
I'm trying to send a request to a local server running HTTP/2 without TLS (H2C) over a unix domain socket. This is what my company uses for internal services.
However, when I try to fetch the results, I git an SSL error:
{"library":"SSL routines","reason":"wrong version number","code":"ERR_SSL_WRONG_VERSION_NUMBER"} (fetch) TypeError: fetch failed
Reproducible By
I'm using node to start the local server:
import { createServer } from 'node:http2';
const server = createServer();
// ...define services.
server.listen('/tmp/test.sock');
I can successfully query the local server via curl:
curl -k -v \
--unix-socket "/tmp/test.sock" \
--insecure \
-d '{"message":"test"}' \
-H "Content-Type: application/json" \
--http2-prior-knowledge \
http://localhost/api/demo_rest
But it doesn't work when querying using undici:
import { Agent, fetch as undiciFetch } from 'undici';
const localhostAgent = new Agent({
connect: {
socketPath: '/tmp/test.sock',
rejectUnauthorized: false,
requestCert: false,
},
allowH2: true,
});
await undiciFetch('http://localhost/api/demo_rest', {
body: JSON.stringify({ message: 'Greetings' }),
headers: { 'Content-type': 'application/json' },
method: 'POST',
dispatcher: localhostAgent,
});
Expected Behavior
The expected behavior is that when a dispatcher does not request a cert, the fetch is able to make a request to an HTTP/2 server over a unix domain socket.
Logs & Screenshots
N/A
Environment
MacOs 14
Additional context
It feels really weird that I can easily start an insecure HTTP2 server using node, but it's very hard (or impossible) to send requests to it.
Currently we do not support H2C. A PR that adds support would be amazing.
I've been playing around with this recently, and I believe that is not an easy task given the little context we know when instantiating a plain text connection.
There's no way to differentiate when we are communicating through h2c or plain http/1.1; by setting allowH2: true we can assume that all requests will be h2c if going over an unencrypted channel, but it's problematic to assume all connections will be over h2c, especially as there are just little servers outside supporting this mode.
My thought will be to make this mostly a proper Agent (i.e. H2CAgent or something) so it can be safely used and up to the implementer if they want to customize undici to always assume h2c in plain text connections. wdyt?
cc: @mcollina @ronag
I think something lower level would be better. IMHO a H2CPool would be low level and composable enough.