feat(interceptor): add HTTP/2 h2c support for cleartext connections#1394
feat(interceptor): add HTTP/2 h2c support for cleartext connections#1394starlightromero wants to merge 1 commit intokedacore:mainfrom
Conversation
Enable HTTP/2 cleartext (h2c) protocol support for non-TLS connections in the interceptor proxy server. This allows AWS Application Load Balancers and other clients to communicate with the interceptor using HTTP/2 over plain HTTP. When tlsConfig is nil, the handler is wrapped with h2c.NewHandler to support both HTTP/2 prior knowledge and HTTP/1.1 connections. TLS connections remain unchanged and continue to support native HTTP/2 over TLS. This change enables the use of appProtocol: kubernetes.io/h2c on Kubernetes Services, which instructs the AWS Load Balancer Controller to create target groups with ProtocolVersion: HTTP2 for improved performance and efficiency. Changes: - Wrap non-TLS handlers with h2c.NewHandler in pkg/http/server.go - Add golang.org/x/net/http2 dependency for h2c support - Add comprehensive test coverage for both HTTP/1.1 and HTTP/2 h2c - Maintain backwards compatibility with HTTP/1.1 clients Fixes: Enables HTTP/2 h2c support from ALB to interceptor pods Signed-off-by: Starlight Romero <[email protected]>
|
| Status | Scanner | Total (0) | ||||
|---|---|---|---|---|---|---|
| Open Source Security | 0 | 0 | 0 | 0 | See details |
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.
linkvt
left a comment
There was a problem hiding this comment.
Hi @starlightromero ,
thanks for the PR! I left a few comments but also think that we would benefit from a written design in an issue here in the repo - at least in my opinion.
I'm not a maintainer of this project though.
| if tlsConfig == nil { | ||
| h2s := &http2.Server{} | ||
| hdl = h2c.NewHandler(hdl, h2s) | ||
| } |
There was a problem hiding this comment.
golang has HTTP2 support for server and clients in its standard library, they added it quite recently: https://go.dev/doc/go1.24#nethttppkgnethttp
I would prefer using that over the extended standard library as they already plan to deprecate the golang.org/x/net/http2/client subpackage: golang/go#72039
| Handler: hdl, | ||
| Addr: addr, | ||
| TLSConfig: tlsConfig, | ||
| } |
There was a problem hiding this comment.
How do we handle:
- HTTP1 connections to services responding with h2c
- h2c connections to services responding with HTTP1?
| DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) { | ||
| // Use standard dialer for h2c (cleartext HTTP/2) | ||
| return net.Dial(network, addr) | ||
| }, |
There was a problem hiding this comment.
Is this actually needed/used during an non HTTPS request?
| ctx, cancel := context.WithCancel(context.Background()) | ||
| defer cancel() | ||
|
|
||
| serverAddr := "127.0.0.1:18888" |
There was a problem hiding this comment.
I think we should not expect a specific port on a system to be free for us to use during a test. I know that the httptest package can pick a selected port, not sure if we can use it here, but maybe there is another way to get a port thats always free to use.
| @@ -0,0 +1,90 @@ | |||
| package http | |||
There was a problem hiding this comment.
IMO we should have e2e tests covering the different scenarios here (client uses http1/h2c, user application supports http1/h2c/both) as unit tests would not cover all cases.
There was a problem hiding this comment.
Pull request overview
This PR adds HTTP/2 cleartext (h2c) protocol support to the KEDA HTTP Add-on interceptor proxy server, enabling AWS Application Load Balancers and other clients to communicate using HTTP/2 over plain HTTP connections. This addresses the compatibility issue when using appProtocol: kubernetes.io/h2c on Kubernetes Services with AWS Load Balancer Controller.
Changes:
- Added h2c support by wrapping non-TLS handlers with
golang.org/x/net/http2/h2cpackage - Introduced comprehensive test coverage for both HTTP/1.1 and HTTP/2 h2c protocols
- Updated dependency
golang.org/x/netto support h2c functionality
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| pkg/http/server.go | Wraps non-TLS handlers with h2c.NewHandler to enable HTTP/2 cleartext support while preserving HTTP/1.1 compatibility |
| pkg/http/h2c_test.go | New test file validating both HTTP/1.1 and HTTP/2 h2c protocol handling |
| go.mod | Updates golang.org/x/net dependency and related transitive dependencies to support h2c |
| go.sum | Checksums for updated dependencies |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } | ||
| defer resp.Body.Close() | ||
|
|
||
| body, _ := io.ReadAll(resp.Body) |
There was a problem hiding this comment.
The test ignores errors from ReadAll. While this is in a test and the error is unlikely, it's better to be consistent with error handling. Consider checking the error or using an explicit underscore to indicate intentional ignoring.
| } | ||
| defer resp.Body.Close() | ||
|
|
||
| body, _ := io.ReadAll(resp.Body) |
There was a problem hiding this comment.
The test ignores errors from ReadAll. While this is in a test and the error is unlikely, it's better to be consistent with error handling. Consider checking the error or using an explicit underscore to indicate intentional ignoring.
| // Wait for server to start | ||
| time.Sleep(500 * time.Millisecond) |
There was a problem hiding this comment.
Using a hardcoded sleep to wait for server startup is flaky and can cause intermittent test failures. Consider using a retry loop with a timeout to check if the server is accepting connections, or implement a readiness signal from the server goroutine.
Description
This PR adds HTTP/2 cleartext (h2c) protocol support to the interceptor proxy server, enabling AWS Application Load Balancers and other clients to communicate using HTTP/2 over plain HTTP.
Changes
golang.org/x/net/http2for h2c supportpkg/http/h2c_test.gofor both HTTP/1.1 and HTTP/2 h2cMotivation
When using the AWS Load Balancer Controller Gateway API implementation, setting
appProtocol: kubernetes.io/h2con a Kubernetes Service instructs the controller to create ALB target groups withProtocolVersion: HTTP2. However, the KEDA HTTP Add-on interceptor did not support h2c, causing health checks and traffic to fail.This change enables:
appProtocol: kubernetes.io/h2con Kubernetes ServicesHow It Works
The implementation wraps non-TLS handlers with
h2c.NewHandler, which automatically:TLS connections remain unchanged and continue to use native HTTP/2 over TLS.
Testing
TestHTTP2H2CSupportvalidates both HTTP/1.1 and HTTP/2 h2c functionalityChecklist
make test)Fixes #1397