sigs.k8s.io/gateway-api@v1.0.0/conformance/tests/httproute-redirect-port-and-scheme.go (about) 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 "testing" 21 22 "k8s.io/apimachinery/pkg/types" 23 24 "sigs.k8s.io/gateway-api/conformance/utils/http" 25 "sigs.k8s.io/gateway-api/conformance/utils/kubernetes" 26 "sigs.k8s.io/gateway-api/conformance/utils/roundtripper" 27 "sigs.k8s.io/gateway-api/conformance/utils/suite" 28 "sigs.k8s.io/gateway-api/conformance/utils/tls" 29 ) 30 31 func init() { 32 ConformanceTests = append(ConformanceTests, HTTPRouteRedirectPortAndScheme) 33 } 34 35 var HTTPRouteRedirectPortAndScheme = suite.ConformanceTest{ 36 ShortName: "HTTPRouteRedirectPortAndScheme", 37 Description: "An HTTPRoute with port and scheme redirect filter", 38 Manifests: []string{"tests/httproute-redirect-port-and-scheme.yaml"}, 39 Features: []suite.SupportedFeature{ 40 suite.SupportGateway, 41 suite.SupportHTTPRoute, 42 suite.SupportHTTPRoutePortRedirect, 43 suite.SupportGatewayPort8080, 44 }, 45 Test: func(t *testing.T, suite *suite.ConformanceTestSuite) { 46 ns := "gateway-conformance-infra" 47 48 gwNN := types.NamespacedName{Name: "same-namespace", Namespace: ns} 49 routeNN := types.NamespacedName{Name: "http-route-for-listener-on-port-80", Namespace: ns} 50 gwAddr80 := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) 51 kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) 52 53 gwNN = types.NamespacedName{Name: "same-namespace-with-http-listener-on-8080", Namespace: ns} 54 routeNN = types.NamespacedName{Name: "http-route-for-listener-on-port-8080", Namespace: ns} 55 gwAddr8080 := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) 56 kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) 57 58 gwNN = types.NamespacedName{Name: "same-namespace-with-https-listener", Namespace: ns} 59 routeNN = types.NamespacedName{Name: "http-route-for-listener-on-port-443", Namespace: ns} 60 gwAddr443 := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN) 61 kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN) 62 63 certNN := types.NamespacedName{Name: "tls-validity-checks-certificate", Namespace: ns} 64 cPem, keyPem, err := GetTLSSecret(suite.Client, certNN) 65 if err != nil { 66 t.Fatalf("unexpected error finding TLS secret: %v", err) 67 } 68 69 // NOTE: In all the test cases, a missing value of expected Port within 70 // RedirectRequest implies that it is still valid and acceptable for a 71 // port to be specified in the redirect if it corresponds to the scheme 72 // (80 and 443). 73 74 //////////////////////////////////////////////////////////////////////////// 75 // Test cases that use http-route-for-listener-on-port-80 76 //////////////////////////////////////////////////////////////////////////// 77 78 testCases := []http.ExpectedResponse{ 79 { 80 Request: http.Request{ 81 Path: "/scheme-nil-and-port-nil", 82 UnfollowRedirect: true, 83 }, 84 Response: http.Response{StatusCode: 302}, 85 RedirectRequest: &roundtripper.RedirectRequest{ 86 Scheme: "http", 87 Host: "example.org", 88 }, 89 Namespace: ns, 90 }, 91 { 92 Request: http.Request{ 93 Path: "/scheme-nil-and-port-80", 94 UnfollowRedirect: true, 95 }, 96 Response: http.Response{StatusCode: 302}, 97 RedirectRequest: &roundtripper.RedirectRequest{ 98 Scheme: "http", 99 Host: "example.org", 100 }, 101 Namespace: ns, 102 }, 103 { 104 Request: http.Request{ 105 Path: "/scheme-nil-and-port-8080", 106 UnfollowRedirect: true, 107 }, 108 Response: http.Response{StatusCode: 302}, 109 RedirectRequest: &roundtripper.RedirectRequest{ 110 Scheme: "http", 111 Port: "8080", 112 Host: "example.org", 113 }, 114 Namespace: ns, 115 }, 116 { 117 Request: http.Request{ 118 Path: "/scheme-https-and-port-nil", 119 UnfollowRedirect: true, 120 }, 121 Response: http.Response{StatusCode: 302}, 122 RedirectRequest: &roundtripper.RedirectRequest{ 123 Scheme: "https", 124 Host: "example.org", 125 }, 126 Namespace: ns, 127 }, 128 { 129 Request: http.Request{ 130 Path: "/scheme-https-and-port-443", 131 UnfollowRedirect: true, 132 }, 133 Response: http.Response{StatusCode: 302}, 134 RedirectRequest: &roundtripper.RedirectRequest{ 135 Scheme: "https", 136 Host: "example.org", 137 }, 138 Namespace: ns, 139 }, 140 { 141 Request: http.Request{ 142 Path: "/scheme-https-and-port-8443", 143 UnfollowRedirect: true, 144 }, 145 Response: http.Response{StatusCode: 302}, 146 RedirectRequest: &roundtripper.RedirectRequest{ 147 Scheme: "https", 148 Port: "8443", 149 Host: "example.org", 150 }, 151 Namespace: ns, 152 }, 153 } 154 155 for i := range testCases { 156 tc := testCases[i] 157 t.Run("http-listener-on-80/"+tc.GetTestCaseName(i), func(t *testing.T) { 158 t.Parallel() 159 http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr80, tc) 160 }) 161 } 162 163 //////////////////////////////////////////////////////////////////////////// 164 // Test cases that use same-namespace-with-http-listener-on-8080 165 //////////////////////////////////////////////////////////////////////////// 166 167 testCases = []http.ExpectedResponse{ 168 { 169 Request: http.Request{ 170 Path: "/scheme-nil-and-port-nil", 171 UnfollowRedirect: true, 172 }, 173 Response: http.Response{StatusCode: 302}, 174 RedirectRequest: &roundtripper.RedirectRequest{ 175 Scheme: "http", 176 Port: "8080", 177 Host: "example.org", 178 }, 179 Namespace: ns, 180 }, 181 { 182 Request: http.Request{ 183 Path: "/scheme-nil-and-port-80", 184 UnfollowRedirect: true, 185 }, 186 Response: http.Response{StatusCode: 302}, 187 RedirectRequest: &roundtripper.RedirectRequest{ 188 Scheme: "http", 189 Host: "example.org", 190 }, 191 Namespace: ns, 192 }, 193 { 194 Request: http.Request{ 195 Path: "/scheme-https-and-port-nil", 196 UnfollowRedirect: true, 197 }, 198 Response: http.Response{StatusCode: 302}, 199 RedirectRequest: &roundtripper.RedirectRequest{ 200 Scheme: "https", 201 Host: "example.org", 202 }, 203 Namespace: ns, 204 }, 205 } 206 207 for i := range testCases { 208 tc := testCases[i] 209 t.Run("http-listener-on-8080/"+tc.GetTestCaseName(i), func(t *testing.T) { 210 t.Parallel() 211 http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr8080, tc) 212 }) 213 } 214 215 //////////////////////////////////////////////////////////////////////////// 216 // Test cases that use http-route-for-listener-on-port-443 217 //////////////////////////////////////////////////////////////////////////// 218 219 testCases = []http.ExpectedResponse{ 220 { 221 Request: http.Request{ 222 Host: "example.org", 223 Path: "/scheme-nil-and-port-nil", 224 UnfollowRedirect: true, 225 }, 226 Response: http.Response{StatusCode: 302}, 227 RedirectRequest: &roundtripper.RedirectRequest{ 228 Scheme: "https", 229 Host: "example.org", 230 }, 231 Namespace: ns, 232 }, 233 { 234 Request: http.Request{ 235 Host: "example.org", 236 Path: "/scheme-nil-and-port-443", 237 UnfollowRedirect: true, 238 }, 239 Response: http.Response{StatusCode: 302}, 240 RedirectRequest: &roundtripper.RedirectRequest{ 241 Scheme: "https", 242 Host: "example.org", 243 }, 244 Namespace: ns, 245 }, 246 { 247 Request: http.Request{ 248 Host: "example.org", 249 Path: "/scheme-nil-and-port-8443", 250 UnfollowRedirect: true, 251 }, 252 Response: http.Response{StatusCode: 302}, 253 RedirectRequest: &roundtripper.RedirectRequest{ 254 Scheme: "https", 255 Port: "8443", 256 Host: "example.org", 257 }, 258 Namespace: ns, 259 }, 260 { 261 Request: http.Request{ 262 Host: "example.org", 263 Path: "/scheme-http-and-port-nil", 264 UnfollowRedirect: true, 265 }, 266 Response: http.Response{StatusCode: 302}, 267 RedirectRequest: &roundtripper.RedirectRequest{ 268 Scheme: "http", 269 Host: "example.org", 270 }, 271 Namespace: ns, 272 }, 273 { 274 Request: http.Request{ 275 Host: "example.org", 276 Path: "/scheme-http-and-port-80", 277 UnfollowRedirect: true, 278 }, 279 Response: http.Response{StatusCode: 302}, 280 RedirectRequest: &roundtripper.RedirectRequest{ 281 Scheme: "http", 282 Host: "example.org", 283 }, 284 Namespace: ns, 285 }, 286 { 287 Request: http.Request{ 288 Host: "example.org", 289 Path: "/scheme-http-and-port-8080", 290 UnfollowRedirect: true, 291 }, 292 Response: http.Response{StatusCode: 302}, 293 RedirectRequest: &roundtripper.RedirectRequest{ 294 Scheme: "http", 295 Port: "8080", 296 Host: "example.org", 297 }, 298 Namespace: ns, 299 }, 300 } 301 302 for i := range testCases { 303 tc := testCases[i] 304 t.Run("https-listener-on-443/"+tc.GetTestCaseName(i), func(t *testing.T) { 305 t.Parallel() 306 tls.MakeTLSRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr443, cPem, keyPem, "example.org", tc) 307 }) 308 } 309 }, 310 }