A simple Node.js module that creates a server supporting both HTTP/1.1 and HTTP/2 cleartext (h2c) on the same port
npm install srvh2ch11A simple Node.js module that creates a server supporting both HTTP/1.1 and HTTP/2 cleartext (h2c) with prior knowledge on the same port.
HTTP/1.1 has security limitations when used for connections from reverse proxies to upstream servers (http1mustdie.com). HTTP/2 offers significant improvements, but within secure networks and internal infrastructure, managing TLS certificates adds unnecessary complexity.
HTTP/2 Cleartext (h2c) provides some security benefits of HTTP/2 without requiring TLS (clear separation of request body and headers). However, migrating infrastructure from HTTP/1.1 to h2c requires a transition period where both protocols must be supported.
While Node.js's http2.createServer has an allowHTTP1 option, it only works with TLS connections. There are no plans to fix this limitation (nodejs/node#44887).
Hence this package.
srvh2ch11 solves this by:
1. Creating a raw TCP server that listens for incoming connections
2. Sniffing the initial bytes to detect the HTTP/2 connection preface (PRI * HTTP/2.0)
3. Routing the connection to either an HTTP/1.1 or HTTP/2 server based on the detected protocol
Important: This module only supports HTTP/2 with prior knowledge. The client must know in advance that the server supports HTTP/2 cleartext and send the connection preface immediately. There is no HTTP/1.1 to HTTP/2 upgrade negotiation.
``bash`
npm install srvh2ch11
`javascript
import srvh2ch11 from "srvh2ch11";
const server = srvh2ch11.createServer((req, res) => {
res.writeHead(200, { "Content-Type": "text/plain" });
res.end("Hello from HTTP/" + req.httpVersion);
});
server.listen(8080, () => {
console.log("Server listening on port 8080");
});
`
`javascript
import srvh2ch11 from "srvh2ch11";
const options = {
http1: {
// HTTP/1.1 specific options
},
http2: {
// HTTP/2 specific options
maxConcurrentStreams: 100
}
};
const server = srvh2ch11.createServer(options, (req, res) => {
res.writeHead(200, { "Content-Type": "text/plain" });
res.end("Hello from HTTP/" + req.httpVersion);
});
server.listen(8080);
`
`javascript
import srvh2ch11 from "srvh2ch11";
const options = {
forceH2c: process.env.SRV_FORCE_H2C === "true", // Only accept H2C connections in production
http2: {
maxConcurrentStreams: 100
}
};
const server = srvh2ch11.createServer(options, (req, res) => {
res.writeHead(200, { "Content-Type": "text/plain" });
res.end("Hello from HTTP/" + req.httpVersion);
});
server.listen(8080);
`
Run with:
`bash`
SRV_FORCE_H2C=true node server.js
Creates a server that can handle both HTTP/1.1 and HTTP/2 cleartext connections.
- options (optional): Configuration object with the following structure:http1
- : Options passed to http.createServer()http2
- : Options passed to http2.createServer()forceH2c
- : Boolean (default: false) - When true, forces HTTP/2-only mode, bypassing protocol detection and rejecting HTTP/1.1 connectionshttp11Compat
- : Boolean (default: false) - When true, enables HTTP/1.1 compatibility transformations for HTTP/2 requests::authority
- Maps header to host headeronRequestHandler
- Filters out HTTP/1.1-specific headers (connection, keep-alive, etc.) to prevent warnings
- : The request handler function with signature (req, res) => {}
Returns an object with:
- listen(port, [callback]): Start listening on the specified portclose([callback])
- : Close all servers (raw, HTTP/1.1, and HTTP/2)on(event, handler)
- : Add event listenersaddress()
- : Get the server addressh1Server
- : The underlying HTTP/1.1 server instanceh2Server
- : The underlying HTTP/2 server instancerawServer
- : The underlying raw TCP server instance
Test with HTTP/1.1:
`bash`
curl http://localhost:8080/
Test with HTTP/2:
`bash`
curl --http2-prior-knowledge http://localhost:8080/
Run the included example:
`bash`
npm run example
The module includes comprehensive test suites:
`bash`Run tests (automatically builds TypeScript first)
npm test
`bash`Run basic curl tests (automatically builds TypeScript first)
npm run test:bash
`bash`Test against Node.js 20, 22, and 24
npm run test:multi
The tests cover:
- HTTP/1.1 GET, POST, and concurrent requests
- HTTP/2 with prior knowledge (GET, POST, concurrent streams)
- Mixed protocol handling (HTTP/1.1 and HTTP/2 simultaneously)
- Server configuration with separate options
- Force HTTP/2-only mode (forceH2c option)http11Compat
- HTTP/1.1 compatibility mode ( option)
- Basic curl-based integration tests
- Compatibility across multiple Node.js versions (20, 22, 24)
- HTTP/2 module maturity: Node.js's http2 module is less mature than http. For example, it doesn't offer closeAllConnections() and closeIdleConnections() methods that are available in the HTTP/1.1 server. There may be other API gaps as well.http2.createSecureServer()
- Prior knowledge only: This module only supports HTTP/2 with prior knowledge. There is no HTTP/1.1 to HTTP/2 upgrade negotiation (note that Upgrade negotiation has been deprecated by RFC 9113 anyway).
- Cleartext only: This module is designed for cleartext (non-TLS) connections. For TLS connections, use Node.js's native with allowHTTP1: true`.
Thanks to GitHub users @fkoemep and @stT-e5gna2z5MBS who shared example implementations in the Node.js issue #44887.
This package was made possible by Hypersequent, creators of QA Sphere - a fast, pleasant to use Test Management System.
MIT