Skip to content

Commit afc0295

Browse files
committed
GEP-1911 - h2c backend protocol
1 parent 38125d1 commit afc0295

File tree

6 files changed

+136
-17
lines changed

6 files changed

+136
-17
lines changed

conformance/base/manifests.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ spec:
9494
- protocol: TCP
9595
port: 8080
9696
targetPort: 3000
97+
- protocol: TCP
98+
appProtocol: kubernetes.io/h2c
99+
port: 8081
100+
targetPort: 3001
97101
---
98102
apiVersion: apps/v1
99103
kind: Deployment
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
Copyright 2023 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package tests
18+
19+
import (
20+
"context"
21+
"crypto/tls"
22+
"net"
23+
"testing"
24+
25+
"golang.org/x/net/http2"
26+
27+
"k8s.io/apimachinery/pkg/types"
28+
29+
"sigs.k8s.io/gateway-api/conformance/utils/http"
30+
"sigs.k8s.io/gateway-api/conformance/utils/kubernetes"
31+
"sigs.k8s.io/gateway-api/conformance/utils/suite"
32+
)
33+
34+
func init() {
35+
ConformanceTests = append(ConformanceTests, HTTPRouteBackendProtocolH2C)
36+
}
37+
38+
var HTTPRouteBackendProtocolH2C = suite.ConformanceTest{
39+
ShortName: "HTTPRouteBackendProtocolH2C",
40+
Description: "A HTTPRoute with a BackendRef that has an appProtocol kubernetes.io/h2c should be functional",
41+
Features: []suite.SupportedFeature{
42+
suite.SupportGateway,
43+
suite.SupportHTTPRoute,
44+
suite.SupportHTTPRouteBackendProtocolH2C,
45+
},
46+
Manifests: []string{
47+
"tests/httproute-backend-protocol-h2c.yaml",
48+
},
49+
Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
50+
ns := "gateway-conformance-infra"
51+
routeNN := types.NamespacedName{Name: "backend-protocol-h2c", Namespace: ns}
52+
gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns}
53+
gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN)
54+
55+
t.Run("http2 prior knowledge request should reach backend", func(t *testing.T) {
56+
http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, http.ExpectedResponse{
57+
Request: http.Request{
58+
Transport: &http2.Transport{
59+
AllowHTTP: true,
60+
DialTLSContext: func(ctx context.Context, network, addr string, cfg *tls.Config) (net.Conn, error) {
61+
var d net.Dialer
62+
return d.DialContext(ctx, network, addr)
63+
},
64+
},
65+
},
66+
Response: http.Response{StatusCode: 200},
67+
Backend: "infra-backend-v1",
68+
Namespace: "gateway-conformance-infra",
69+
})
70+
})
71+
72+
t.Run("h2c upgrade request should reach backend", func(t *testing.T) {
73+
http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, http.ExpectedResponse{
74+
Request: http.Request{
75+
Headers: map[string]string{
76+
"HTTP2-Settings": "",
77+
"Connection": "Upgrade, HTTP2-Settings",
78+
},
79+
},
80+
Response: http.Response{StatusCode: 200},
81+
Backend: "infra-backend-v1",
82+
Namespace: "gateway-conformance-infra",
83+
})
84+
})
85+
},
86+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
apiVersion: gateway.networking.k8s.io/v1beta1
2+
kind: HTTPRoute
3+
metadata:
4+
name: backend-protocol-h2c
5+
namespace: gateway-conformance-infra
6+
spec:
7+
parentRefs:
8+
- name: same-namespace
9+
rules:
10+
- backendRefs:
11+
# This points to a Service with the following ServicePort
12+
# - protocol: TCP
13+
# appProtocol: kubernetes.io/h2c
14+
# port: 8081
15+
# targetPort: 3001
16+
- name: infra-backend-v1
17+
port: 8081

conformance/utils/http/http.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package http
1919
import (
2020
"fmt"
2121
"net"
22+
"net/http"
2223
"net/url"
2324
"strings"
2425
"testing"
@@ -69,6 +70,7 @@ type Request struct {
6970
Headers map[string]string
7071
UnfollowRedirect bool
7172
Protocol string
73+
Transport http.RoundTripper
7274
}
7375

7476
// ExpectedRequest defines expected properties of a request that reaches a backend.
@@ -128,6 +130,7 @@ func MakeRequest(t *testing.T, expected *ExpectedResponse, gwAddr, protocol, sch
128130
Protocol: protocol,
129131
Headers: map[string][]string{},
130132
UnfollowRedirect: expected.Request.UnfollowRedirect,
133+
Transport: expected.Request.Transport,
131134
}
132135

133136
if expected.Request.Headers != nil {

conformance/utils/roundtripper/roundtripper.go

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ type Request struct {
4949
CertPem []byte
5050
KeyPem []byte
5151
Server string
52+
Transport http.RoundTripper
5253
}
5354

5455
// String returns a printable version of Request for logging. Note that the
@@ -117,25 +118,29 @@ func (d *DefaultRoundTripper) CaptureRoundTrip(request Request) (*CapturedReques
117118
}
118119
}
119120

120-
transport := &http.Transport{
121-
DialContext: d.CustomDialContext,
122-
// We disable keep-alives so that we don't leak established TCP connections.
123-
// Leaking TCP connections is bad because we could eventually hit the
124-
// threshold of maximum number of open TCP connections to a specific
125-
// destination. Keep-alives are not presently utilized so disabling this has
126-
// no adverse affect.
127-
//
128-
// Ref. https://github.com/kubernetes-sigs/gateway-api/issues/2357
129-
DisableKeepAlives: true,
130-
}
131-
if request.Server != "" && len(request.CertPem) != 0 && len(request.KeyPem) != 0 {
132-
tlsConfig, err := tlsClientConfig(request.Server, request.CertPem, request.KeyPem)
133-
if err != nil {
134-
return nil, nil, err
121+
if request.Transport != nil {
122+
client.Transport = request.Transport
123+
} else {
124+
transport := &http.Transport{
125+
DialContext: d.CustomDialContext,
126+
// We disable keep-alives so that we don't leak established TCP connections.
127+
// Leaking TCP connections is bad because we could eventually hit the
128+
// threshold of maximum number of open TCP connections to a specific
129+
// destination. Keep-alives are not presently utilized so disabling this has
130+
// no adverse affect.
131+
//
132+
// Ref. https://github.com/kubernetes-sigs/gateway-api/issues/2357
133+
DisableKeepAlives: true,
134+
}
135+
if request.Server != "" && len(request.CertPem) != 0 && len(request.KeyPem) != 0 {
136+
tlsConfig, err := tlsClientConfig(request.Server, request.CertPem, request.KeyPem)
137+
if err != nil {
138+
return nil, nil, err
139+
}
140+
transport.TLSClientConfig = tlsConfig
135141
}
136-
transport.TLSClientConfig = tlsConfig
142+
client.Transport = transport
137143
}
138-
client.Transport = transport
139144

140145
method := "GET"
141146
if request.Method != "" {

conformance/utils/suite/features.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ const (
121121

122122
// This option indicates support for multiple RequestMirror filters within the same HTTPRoute rule (extended conformance).
123123
SupportHTTPRouteRequestMultipleMirrors SupportedFeature = "HTTPRouteRequestMultipleMirrors"
124+
125+
// This option indicates support for HTTPRoute with a backendref with an appProtoocol 'kubernetes.io/h2c'
126+
SupportHTTPRouteBackendProtocolH2C SupportedFeature = "HTTPRouteBackendProtocolH2C"
124127
)
125128

126129
// HTTPRouteExtendedFeatures includes all the supported features for HTTPRoute
@@ -137,6 +140,7 @@ var HTTPRouteExtendedFeatures = sets.New(
137140
SupportHTTPRoutePathRewrite,
138141
SupportHTTPRouteRequestMirror,
139142
SupportHTTPRouteRequestMultipleMirrors,
143+
SupportHTTPRouteBackendProtocolH2C,
140144
)
141145

142146
// -----------------------------------------------------------------------------

0 commit comments

Comments
 (0)