Skip to content

Commit

Permalink
allow retaining a trailing slash in a TLS redirect via annotation.
Browse files Browse the repository at this point in the history
Signed-off-by: mamiller <mamiller@rosettastone.com>
  • Loading branch information
mmiller1 committed May 18, 2021
1 parent 93070fa commit 6d4efc4
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 3 deletions.
3 changes: 3 additions & 0 deletions internal/ingress/annotations/rewrite/main.go
Expand Up @@ -35,6 +35,8 @@ type Config struct {
SSLRedirect bool `json:"sslRedirect"`
// ForceSSLRedirect indicates if the location section is accessible SSL only
ForceSSLRedirect bool `json:"forceSSLRedirect"`
// PreserveTrailingSlash indicates if the trailing slash should be kept during a tls redirect
PreserveTrailingSlash bool `json:"preserveTrailingSlash"`
// AppRoot defines the Application Root that the Controller must redirect if it's in '/' context
AppRoot string `json:"appRoot"`
// UseRegex indicates whether or not the locations use regex paths
Expand Down Expand Up @@ -85,6 +87,7 @@ func (a rewrite) Parse(ing *networking.Ingress) (interface{}, error) {

config.Target, _ = parser.GetStringAnnotation("rewrite-target", ing)
config.SSLRedirect, err = parser.GetBoolAnnotation("ssl-redirect", ing)
config.PreserveTrailingSlash, err = parser.GetBoolAnnotation("preserve-trailing-slash", ing)
if err != nil {
config.SSLRedirect = a.r.GetDefaultBackend().SSLRedirect
}
Expand Down
2 changes: 2 additions & 0 deletions internal/ingress/controller/template/template.go
Expand Up @@ -342,12 +342,14 @@ func locationConfigForLua(l interface{}, a interface{}) string {
force_ssl_redirect = %t,
ssl_redirect = %t,
force_no_ssl_redirect = %t,
preserve_trailing_slash = %t,
use_port_in_redirects = %t,
global_throttle = { namespace = "%v", limit = %d, window_size = %d, key = %v, ignored_cidrs = %v },
}`,
location.Rewrite.ForceSSLRedirect,
location.Rewrite.SSLRedirect,
isLocationInLocationList(l, all.Cfg.NoTLSRedirectLocations),
location.Rewrite.PreserveTrailingSlash,
location.UsePortInRedirects,
location.GlobalRateLimit.Namespace,
location.GlobalRateLimit.Limit,
Expand Down
8 changes: 5 additions & 3 deletions rootfs/etc/nginx/lua/lua_ingress.lua
Expand Up @@ -147,9 +147,11 @@ function _M.rewrite(location_config)

if redirect_to_https(location_config) then
local request_uri = ngx.var.request_uri
-- do not append a trailing slash on redirects
if string.sub(request_uri, -1) == "/" then
request_uri = string.sub(request_uri, 1, -2)
-- do not append a trailing slash on redirects unless enabled by annotations
if location_config.preserve_trailing_slash == false then
if string.sub(request_uri, -1) == "/" then
request_uri = string.sub(request_uri, 1, -2)
end
end

local uri = string_format("https://%s%s", redirect_host(), request_uri)
Expand Down
53 changes: 53 additions & 0 deletions test/e2e/annotations/preservetrailingslash.go
@@ -0,0 +1,53 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package annotations

import (
"net/http"

"github.com/onsi/ginkgo"

"k8s.io/ingress-nginx/test/e2e/framework"
)

var _ = framework.DescribeAnnotation("preserve-trailing-slash", func() {
f := framework.NewDefaultFramework("preservetrailingslash")

ginkgo.BeforeEach(func() {
f.NewEchoDeployment()
})

ginkgo.It("should allow preservation of trailing slashes", func() {
host := "forcesslredirect.bar.com"
tlsHosts := []string{host}

annotations := map[string]string{
"nginx.ingress.kubernetes.io/ssl-redirect": "true",
"nginx.ingress.kubernetes.io/preserve-trailing-slash": "true",
}

ing := framework.NewSingleIngressWithTLS(host, "/", host, tlsHosts, f.Namespace, framework.EchoService, 80, annotations)
f.EnsureIngress(ing)

f.HTTPTestClient().
GET("/").
WithHeader("Host", host).
Expect().
Status(http.StatusPermanentRedirect).
Header("Location").Equal("https://forcesslredirect.bar.com/")
})
})

0 comments on commit 6d4efc4

Please sign in to comment.