The documentation for public network services states that:
If your application stack has good HTTP/2 support (like Go), you will get better performance accepting TCP connections directly, and using the TLS handler to terminate SSL. Your application does need to understand
h2c
for this to work, however.
My setup is as follows:
[[services]]
internal_port = 8080
protocol = "tcp"
auto_stop_machines = false
auto_start_machines = true
min_machines_running = 0
[[services.ports]]
handlers = ["http"]
port = "80"
force_https = true
[[services.ports]]
handlers = ["tls"]
port = "443"
and I run an HTTP server on port 8080. Said server, like most Rust HTTP servers, dynamically supports both HTTP/1.1 and HTTP/2 (by trying both and seeïng which parses correctly) but does not support HTTP/1.1 upgrade into HTTP/2. But the behaviour I’m seeïng has been nothing but confusing:
- When
curl
ing the server, the cliënt will seemingly randomly pick between HTTP/2 and HTTP/1.1 despite ALPN always givingh2,http/1.1
; - The HTTP/1.1 requests and responses appear to be “raw”, i.e. with no
fly-client-ip
,server
,via
orfly-request-id
headers added, while the HTTP/2 messages have those headers; - The server, regardless of what
curl
does, always sees an HTTP/1.1 connection with noUpgrade
header.
So what’s goïng on here? What explains the inconsistent behaviour? And more importantly, how can I get my server to actually run HTTP/2 all the way through?
Edit: Nevermind, just had to set tls_options = { alpn = ["h2"] }
.