From 224c6a93048490b5ec200743cb2b6258099d249c Mon Sep 17 00:00:00 2001 From: Anatole Lucet Date: Mon, 15 Jun 2026 14:02:07 +0200 Subject: [PATCH] Fix Gateway API redirect missing statuses --- .../experimental-v3.7-default-report.yaml | 11 ++++--- integration/gateway_api_conformance_test.go | 3 +- .../gatewayapi/redirect/request_redirect.go | 8 ++++- .../redirect/request_redirect_test.go | 32 ++++++++++++++++++- pkg/provider/kubernetes/gateway/features.go | 5 ++- 5 files changed, 51 insertions(+), 8 deletions(-) diff --git a/integration/gateway-api-conformance-reports/v1.5.1/experimental-v3.7-default-report.yaml b/integration/gateway-api-conformance-reports/v1.5.1/experimental-v3.7-default-report.yaml index 8b963c2e1..622f041fb 100644 --- a/integration/gateway-api-conformance-reports/v1.5.1/experimental-v3.7-default-report.yaml +++ b/integration/gateway-api-conformance-reports/v1.5.1/experimental-v3.7-default-report.yaml @@ -30,11 +30,14 @@ profiles: result: success statistics: Failed: 0 - Passed: 20 + Passed: 23 Skipped: 0 supportedFeatures: - BackendTLSPolicy - GatewayPort8080 + - HTTPRoute303RedirectStatusCode + - HTTPRoute307RedirectStatusCode + - HTTPRoute308RedirectStatusCode - HTTPRouteBackendProtocolH2C - HTTPRouteBackendProtocolWebSocket - HTTPRouteBackendRequestHeaderModification @@ -57,9 +60,6 @@ profiles: - GatewayHTTPSListenerDetectMisdirectedRequests - GatewayInfrastructurePropagation - GatewayStaticAddresses - - HTTPRoute303RedirectStatusCode - - HTTPRoute307RedirectStatusCode - - HTTPRoute308RedirectStatusCode - HTTPRouteBackendTimeout - HTTPRouteCORS - HTTPRouteNamedRouteRule @@ -100,5 +100,8 @@ profiles: name: GATEWAY-TLS summary: Core tests succeeded. Extended tests succeeded. succeededProvisionalTests: +- HTTPRoute303Redirect +- HTTPRoute307Redirect +- HTTPRoute308Redirect - TLSRouteMixedTerminationSameNamespace - TLSRouteTerminateSimpleSameNamespace diff --git a/integration/gateway_api_conformance_test.go b/integration/gateway_api_conformance_test.go index 2625adb23..2aa959e12 100644 --- a/integration/gateway_api_conformance_test.go +++ b/integration/gateway_api_conformance_test.go @@ -78,7 +78,8 @@ func (s *GatewayAPIConformanceSuite) SetupSuite() { s.T().Fatal("Traefik image is not present") } - s.k3sContainer, err = k3s.Run(ctx, + s.k3sContainer, err = k3s.Run( + ctx, k3sImage, k3s.WithManifest("./fixtures/gateway-api-conformance/00-experimental-v1.5.1.yml"), k3s.WithManifest("./fixtures/gateway-api-conformance/01-rbac.yml"), diff --git a/pkg/middlewares/gatewayapi/redirect/request_redirect.go b/pkg/middlewares/gatewayapi/redirect/request_redirect.go index 1305a2372..1b7443aa9 100644 --- a/pkg/middlewares/gatewayapi/redirect/request_redirect.go +++ b/pkg/middlewares/gatewayapi/redirect/request_redirect.go @@ -35,7 +35,13 @@ func NewRequestRedirect(ctx context.Context, next http.Handler, conf dynamic.Req if statusCode == 0 { statusCode = http.StatusFound } - if statusCode != http.StatusMovedPermanently && statusCode != http.StatusFound { + + // Comply with HTTPRequestRedirectFilter.StatusCode + if statusCode != http.StatusMovedPermanently && + statusCode != http.StatusFound && + statusCode != http.StatusSeeOther && + statusCode != http.StatusTemporaryRedirect && + statusCode != http.StatusPermanentRedirect { return nil, fmt.Errorf("unsupported status code: %d", statusCode) } diff --git a/pkg/middlewares/gatewayapi/redirect/request_redirect_test.go b/pkg/middlewares/gatewayapi/redirect/request_redirect_test.go index 530027adb..d9a2174c3 100644 --- a/pkg/middlewares/gatewayapi/redirect/request_redirect_test.go +++ b/pkg/middlewares/gatewayapi/redirect/request_redirect_test.go @@ -136,6 +136,36 @@ func TestRequestRedirectHandler(t *testing.T) { wantURL: "http://foo", wantStatus: http.StatusMovedPermanently, }, + { + desc: "303 See Other", + config: dynamic.RequestRedirect{ + Scheme: ptr.To("https"), + StatusCode: http.StatusSeeOther, + }, + url: "http://foo", + wantURL: "https://foo", + wantStatus: http.StatusSeeOther, + }, + { + desc: "307 Temporary Redirect", + config: dynamic.RequestRedirect{ + Scheme: ptr.To("https"), + StatusCode: http.StatusTemporaryRedirect, + }, + url: "http://foo", + wantURL: "https://foo", + wantStatus: http.StatusTemporaryRedirect, + }, + { + desc: "308 Permanent Redirect", + config: dynamic.RequestRedirect{ + Scheme: ptr.To("https"), + StatusCode: http.StatusPermanentRedirect, + }, + url: "http://foo", + wantURL: "https://foo", + wantStatus: http.StatusPermanentRedirect, + }, { desc: "HTTP to HTTPS", config: dynamic.RequestRedirect{ @@ -201,7 +231,7 @@ func TestRequestRedirectHandler(t *testing.T) { assert.Equal(t, test.wantStatus, recorder.Code) switch test.wantStatus { - case http.StatusMovedPermanently, http.StatusFound: + case http.StatusMovedPermanently, http.StatusFound, http.StatusSeeOther, http.StatusTemporaryRedirect, http.StatusPermanentRedirect: location, err := recorder.Result().Location() require.NoError(t, err) diff --git a/pkg/provider/kubernetes/gateway/features.go b/pkg/provider/kubernetes/gateway/features.go index e8c8bd1c5..5cbd176bd 100644 --- a/pkg/provider/kubernetes/gateway/features.go +++ b/pkg/provider/kubernetes/gateway/features.go @@ -44,11 +44,14 @@ func extendedHTTPRouteFeatures() sets.Set[features.Feature] { return sets.New( features.HTTPRouteQueryParamMatchingFeature, features.HTTPRouteMethodMatchingFeature, + features.HTTPRoutePathRedirectFeature, features.HTTPRoutePortRedirectFeature, features.HTTPRouteSchemeRedirectFeature, + features.HTTPRoute303RedirectStatusCodeFeature, + features.HTTPRoute307RedirectStatusCodeFeature, + features.HTTPRoute308RedirectStatusCodeFeature, features.HTTPRouteHostRewriteFeature, features.HTTPRoutePathRewriteFeature, - features.HTTPRoutePathRedirectFeature, features.HTTPRouteResponseHeaderModificationFeature, features.HTTPRouteBackendProtocolH2CFeature, features.HTTPRouteBackendProtocolWebSocketFeature,