diff --git a/internal/ingress/controller/template/template.go b/internal/ingress/controller/template/template.go index 2cc778ac1..ab032b7fe 100644 --- a/internal/ingress/controller/template/template.go +++ b/internal/ingress/controller/template/template.go @@ -317,16 +317,26 @@ func locationConfigForLua(l interface{}, a interface{}) string { return "{}" } + pathType := "" + if location.PathType != nil { + pathType = fmt.Sprintf("%v", *location.PathType) + } + if needsRewrite(location) || location.Rewrite.UseRegex { + pathType = "" + } + return fmt.Sprintf(`{ force_ssl_redirect = %t, ssl_redirect = %t, force_no_ssl_redirect = %t, use_port_in_redirects = %t, + path_type = "%v", }`, location.Rewrite.ForceSSLRedirect, location.Rewrite.SSLRedirect, isLocationInLocationList(l, all.Cfg.NoTLSRedirectLocations), location.UsePortInRedirects, + pathType, ) } diff --git a/rootfs/etc/nginx/lua/lua_ingress.lua b/rootfs/etc/nginx/lua/lua_ingress.lua index dd847cbb4..0200b4682 100644 --- a/rootfs/etc/nginx/lua/lua_ingress.lua +++ b/rootfs/etc/nginx/lua/lua_ingress.lua @@ -97,6 +97,25 @@ local function parse_x_forwarded_host() return hosts[1] end +local function k8s_matches_pathtype_prefix(current_uri, prefix) + if prefix == "/" then + return true + end + if current_uri == prefix then + return true + end + if #current_uri < #prefix then + return false + end + + local _, to = string.find(current_uri, prefix) + if to == nil then + return false + end + + return string.sub(current_uri, to + 1, to + 1) == "/" +end + function _M.init_worker() randomseed() end @@ -109,6 +128,12 @@ end -- This is where we do variable assignments to be used in subsequent -- phases or redirection function _M.rewrite(location_config) + if location_config.path_type == "Prefix" and + not k8s_matches_pathtype_prefix(ngx.var.uri, ngx.var.location_path) then + + return ngx.exit(ngx.HTTP_NOT_FOUND) + end + ngx.var.pass_access_scheme = ngx.var.scheme ngx.var.best_http_host = ngx.var.http_host or ngx.var.host @@ -158,7 +183,7 @@ function _M.rewrite(location_config) config.listen_ports.https, request_uri) end - ngx_redirect(uri, config.http_redirect_code) + return ngx_redirect(uri, config.http_redirect_code) end end diff --git a/test/e2e/ingress/pathtype_prefix.go b/test/e2e/ingress/pathtype_prefix.go new file mode 100644 index 000000000..c2c7b0f8d --- /dev/null +++ b/test/e2e/ingress/pathtype_prefix.go @@ -0,0 +1,71 @@ +/* +Copyright 2019 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 ingress + +import ( + "net/http" + "strings" + + "github.com/onsi/ginkgo" + + "k8s.io/ingress-nginx/test/e2e/framework" +) + +var _ = framework.IngressNginxDescribe("[Ingress] [PathType] prefix checks", func() { + f := framework.NewDefaultFramework("prefix") + + ginkgo.BeforeEach(func() { + f.NewEchoDeployment() + }) + + ginkgo.It("should return 404 when prefix /aaa does not match request /aaaccc", func() { + host := "prefix.path" + + ing := framework.NewSingleIngress("exact", "/aaa", host, f.Namespace, framework.EchoService, 80, nil) + f.EnsureIngress(ing) + + f.WaitForNginxServer(host, + func(server string) bool { + return strings.Contains(server, host) && + strings.Contains(server, "location /aaa") + }) + + f.HTTPTestClient(). + GET("/aaa"). + WithHeader("Host", host). + Expect(). + Status(http.StatusOK) + + f.HTTPTestClient(). + GET("/aaacccc"). + WithHeader("Host", host). + Expect(). + Status(http.StatusNotFound) + + f.HTTPTestClient(). + GET("/aaa/cccc"). + WithHeader("Host", host). + Expect(). + Status(http.StatusOK) + + f.HTTPTestClient(). + GET("/aaa/"). + WithHeader("Host", host). + Expect(). + Status(http.StatusOK) + }) +})