OverviewFilesCommitsIssuesDocsReleasesPeers

7rnx-proxy commits / db44667

1.3.0 — offer h2 ahead of http/1.1
HTTP/2 multiplexes a whole page over ONE connection, so the ~210ms TCP+TLS handshake to this VPS is paid once instead of per parallel connection. Pairs with the KeepAliveTimeout 65 of 1.2.0: that keeps a connection alive between clicks, this stops a page needing several. `Protocols` is a CORE directive (2.4.17+), not one of mod_http2's, so shipping it before `a2enmod http2` is safe — an unavailable protocol is simply never negotiated and clients stay on http/1.1. Verified: deployed with the module still disabled, configtest passed, site healthy, clients still on http/1.1. Emitted at server context above the first <VirtualHost> so the apex site that serves /git inherits it, same as KeepAliveTimeout. Requires mpm_event, which this box already runs — mod_http2 refuses to serve under mpm_prefork. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
db44667ae51e9cd874aed1adfc4691568d99bfad
by plankatron <fleeky@gmail.com> · 2026-08-11T16:47:52.000Z

Changed files (3) +30 -1

lib/config-generator.js +10 -0
……@@ -40,6 +40,16 @@ export function generateVhosts (registry) {
4040 lines.push('KeepAliveTimeout 65')
4141 lines.push('')
4242
43 // h2 multiplexes a whole page over ONE connection, so the ~210ms TCP+TLS
44 // handshake is paid once rather than per parallel connection. `Protocols` is
45 // a CORE directive (2.4.17+), NOT one of mod_http2's, so it is safe to ship
46 // before the module is enabled — an unavailable protocol is simply never
47 // negotiated and clients stay on http/1.1. Requires mpm_event (this box) —
48 // mod_http2 refuses to serve under mpm_prefork.
49 lines.push('# h2 requires `a2enmod http2` + mpm_event; harmless before the module is enabled.')
50 lines.push('Protocols h2 http/1.1')
51 lines.push('')
52
4353 const nodeMap = new Map()
4454 for (const node of registry.nodes) nodeMap.set(node.petname, node)
4555
package.json +1 -1
……@@ -1,6 +1,6 @@
11{
22 "name": "7rnx-proxy",
3 "version": "1.2.0",
3 "version": "1.3.0",
44 "description": "Reverse proxy management CLI for 7rnx.net Apache2 server",
55 "type": "module",
66 "bin": {
test/vhosts.test.js +19 -0
……@@ -63,6 +63,25 @@ describe('generateVhosts (host mode)', () => {
6363 const out = generateVhosts({ nodes: [], hosts: [] })
6464 assert.match(out, /^KeepAliveTimeout 65$/m)
6565 })
66
67 // h2 multiplexes every request for a page over ONE connection, so the ~210ms
68 // handshake is paid once instead of per parallel connection. `Protocols` is a
69 // CORE directive (2.4.17+), so this is valid even before mod_http2 is enabled
70 // — an unavailable protocol is simply never negotiated, and clients stay on
71 // http/1.1. That ordering matters: the config can ship before the module.
72 it('offers h2 ahead of http/1.1 at SERVER context', () => {
73 const out = generateVhosts(registry)
74 assert.match(out, /^Protocols h2 http\/1\.1$/m, 'Protocols emitted')
75
76 const proto = out.search(/^Protocols h2 http\/1\.1$/m)
77 const firstVhost = out.indexOf('<VirtualHost')
78 assert.ok(proto < firstVhost, 'precedes the first VirtualHost so the apex site inherits it')
79 })
80
81 it('emits Protocols even with no hosts registered', () => {
82 const out = generateVhosts({ nodes: [], hosts: [] })
83 assert.match(out, /^Protocols h2 http\/1\.1$/m)
84 })
6685})
6786
6887describe('Registry host methods', () => {