Refactor handling of path Prefix and Exact
This commit is contained in:
parent
52726abaee
commit
3f153add00
10 changed files with 316 additions and 71 deletions
1
go.mod
1
go.mod
|
@ -11,6 +11,7 @@ require (
|
|||
github.com/imdario/mergo v0.3.10
|
||||
github.com/json-iterator/go v1.1.10
|
||||
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348
|
||||
github.com/mitchellh/copystructure v1.0.0
|
||||
github.com/mitchellh/go-ps v1.0.0
|
||||
github.com/mitchellh/hashstructure v1.0.0
|
||||
github.com/mitchellh/mapstructure v1.3.2
|
||||
|
|
4
go.sum
4
go.sum
|
@ -421,6 +421,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182aff
|
|||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
|
||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc=
|
||||
|
@ -435,6 +437,8 @@ github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQz
|
|||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.3.2 h1:mRS76wmkOn3KkKAyXDu42V+6ebnXWIztFSYGN7GeoRg=
|
||||
github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
|
||||
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/mmarkdown/mmark v2.0.40+incompatible h1:vMeUeDzBK3H+/mU0oMVfMuhSXJlIA+DE/DMPQNAj5C4=
|
||||
github.com/mmarkdown/mmark v2.0.40+incompatible/go.mod h1:Uvmoz7tvsWpr7bMVxIpqZPyN3FbOtzDmnsJDFp7ltJs=
|
||||
github.com/moby/sys/mountinfo v0.1.3/go.mod h1:w2t2Avltqx8vE7gX5l+QiBKxODu2TX0+Syr3h52Tw4o=
|
||||
|
|
|
@ -430,6 +430,20 @@ func (n *NGINXController) getConfiguration(ingresses []*ingress.Ingress) (sets.S
|
|||
hosts := sets.NewString()
|
||||
|
||||
for _, server := range servers {
|
||||
// If a location is defined by a prefix string that ends with the slash character, and requests are processed by one of
|
||||
// proxy_pass, fastcgi_pass, uwsgi_pass, scgi_pass, memcached_pass, or grpc_pass, then the special processing is performed.
|
||||
// In response to a request with URI equal to // this string, but without the trailing slash, a permanent redirect with the
|
||||
// code 301 will be returned to the requested URI with the slash appended. If this is not desired, an exact match of the
|
||||
// URIand location could be defined like this:
|
||||
//
|
||||
// location /user/ {
|
||||
// proxy_pass http://user.example.com;
|
||||
// }
|
||||
// location = /user {
|
||||
// proxy_pass http://login.example.com;
|
||||
// }
|
||||
server.Locations = updateServerLocations(server.Locations)
|
||||
|
||||
if !hosts.Has(server.Hostname) {
|
||||
hosts.Insert(server.Hostname)
|
||||
}
|
||||
|
|
|
@ -270,8 +270,6 @@ func TestCheckIngress(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
var pathPrefix = networking.PathTypePrefix
|
||||
|
||||
func TestMergeAlternativeBackends(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
ingress *ingress.Ingress
|
||||
|
@ -295,7 +293,7 @@ func TestMergeAlternativeBackends(t *testing.T) {
|
|||
Paths: []networking.HTTPIngressPath{
|
||||
{
|
||||
Path: "/",
|
||||
PathType: &pathPrefix,
|
||||
PathType: &pathTypePrefix,
|
||||
Backend: networking.IngressBackend{
|
||||
ServiceName: "http-svc-canary",
|
||||
ServicePort: intstr.IntOrString{
|
||||
|
@ -331,7 +329,7 @@ func TestMergeAlternativeBackends(t *testing.T) {
|
|||
Locations: []*ingress.Location{
|
||||
{
|
||||
Path: "/",
|
||||
PathType: &pathPrefix,
|
||||
PathType: &pathTypePrefix,
|
||||
Backend: "example-http-svc-80",
|
||||
},
|
||||
},
|
||||
|
@ -357,7 +355,7 @@ func TestMergeAlternativeBackends(t *testing.T) {
|
|||
Locations: []*ingress.Location{
|
||||
{
|
||||
Path: "/",
|
||||
PathType: &pathPrefix,
|
||||
PathType: &pathTypePrefix,
|
||||
Backend: "example-http-svc-80",
|
||||
},
|
||||
},
|
||||
|
@ -379,7 +377,7 @@ func TestMergeAlternativeBackends(t *testing.T) {
|
|||
Paths: []networking.HTTPIngressPath{
|
||||
{
|
||||
Path: "/",
|
||||
PathType: &pathPrefix,
|
||||
PathType: &pathTypePrefix,
|
||||
Backend: networking.IngressBackend{
|
||||
ServiceName: "foo-http-svc-canary",
|
||||
ServicePort: intstr.IntOrString{
|
||||
|
@ -399,7 +397,7 @@ func TestMergeAlternativeBackends(t *testing.T) {
|
|||
Paths: []networking.HTTPIngressPath{
|
||||
{
|
||||
Path: "/",
|
||||
PathType: &pathPrefix,
|
||||
PathType: &pathTypePrefix,
|
||||
Backend: networking.IngressBackend{
|
||||
ServiceName: "http-svc-canary",
|
||||
ServicePort: intstr.IntOrString{
|
||||
|
@ -447,7 +445,7 @@ func TestMergeAlternativeBackends(t *testing.T) {
|
|||
Locations: []*ingress.Location{
|
||||
{
|
||||
Path: "/",
|
||||
PathType: &pathPrefix,
|
||||
PathType: &pathTypePrefix,
|
||||
Backend: "example-foo-http-svc-80",
|
||||
},
|
||||
},
|
||||
|
@ -457,7 +455,7 @@ func TestMergeAlternativeBackends(t *testing.T) {
|
|||
Locations: []*ingress.Location{
|
||||
{
|
||||
Path: "/",
|
||||
PathType: &pathPrefix,
|
||||
PathType: &pathTypePrefix,
|
||||
Backend: "example-http-svc-80",
|
||||
},
|
||||
},
|
||||
|
@ -495,7 +493,7 @@ func TestMergeAlternativeBackends(t *testing.T) {
|
|||
Locations: []*ingress.Location{
|
||||
{
|
||||
Path: "/",
|
||||
PathType: &pathPrefix,
|
||||
PathType: &pathTypePrefix,
|
||||
Backend: "example-http-svc-80",
|
||||
},
|
||||
},
|
||||
|
@ -517,7 +515,7 @@ func TestMergeAlternativeBackends(t *testing.T) {
|
|||
Paths: []networking.HTTPIngressPath{
|
||||
{
|
||||
Path: "/",
|
||||
PathType: &pathPrefix,
|
||||
PathType: &pathTypePrefix,
|
||||
Backend: networking.IngressBackend{
|
||||
ServiceName: "http-svc-canary",
|
||||
ServicePort: intstr.IntOrString{
|
||||
|
@ -582,7 +580,7 @@ func TestMergeAlternativeBackends(t *testing.T) {
|
|||
Locations: []*ingress.Location{
|
||||
{
|
||||
Path: "/",
|
||||
PathType: &pathPrefix,
|
||||
PathType: &pathTypePrefix,
|
||||
Backend: "example-http-svc-80",
|
||||
},
|
||||
},
|
||||
|
@ -608,7 +606,7 @@ func TestMergeAlternativeBackends(t *testing.T) {
|
|||
Locations: []*ingress.Location{
|
||||
{
|
||||
Path: "/",
|
||||
PathType: &pathPrefix,
|
||||
PathType: &pathTypePrefix,
|
||||
Backend: "example-http-svc-80",
|
||||
},
|
||||
},
|
||||
|
@ -650,7 +648,7 @@ func TestMergeAlternativeBackends(t *testing.T) {
|
|||
Locations: []*ingress.Location{
|
||||
{
|
||||
Path: "/",
|
||||
PathType: &pathPrefix,
|
||||
PathType: &pathTypePrefix,
|
||||
Backend: "upstream-default-backend",
|
||||
},
|
||||
},
|
||||
|
@ -663,7 +661,7 @@ func TestMergeAlternativeBackends(t *testing.T) {
|
|||
Locations: []*ingress.Location{
|
||||
{
|
||||
Path: "/",
|
||||
PathType: &pathPrefix,
|
||||
PathType: &pathTypePrefix,
|
||||
Backend: "upstream-default-backend",
|
||||
},
|
||||
},
|
||||
|
@ -999,7 +997,7 @@ func TestGetBackendServers(t *testing.T) {
|
|||
Paths: []networking.HTTPIngressPath{
|
||||
{
|
||||
Path: "/",
|
||||
PathType: &pathPrefix,
|
||||
PathType: &pathTypePrefix,
|
||||
Backend: networking.IngressBackend{
|
||||
ServiceName: "http-svc-canary",
|
||||
ServicePort: intstr.IntOrString{
|
||||
|
@ -1059,7 +1057,7 @@ func TestGetBackendServers(t *testing.T) {
|
|||
Paths: []networking.HTTPIngressPath{
|
||||
{
|
||||
Path: "/",
|
||||
PathType: &pathPrefix,
|
||||
PathType: &pathTypePrefix,
|
||||
Backend: networking.IngressBackend{
|
||||
ServiceName: "http-svc",
|
||||
ServicePort: intstr.IntOrString{
|
||||
|
@ -1096,7 +1094,7 @@ func TestGetBackendServers(t *testing.T) {
|
|||
Paths: []networking.HTTPIngressPath{
|
||||
{
|
||||
Path: "/",
|
||||
PathType: &pathPrefix,
|
||||
PathType: &pathTypePrefix,
|
||||
Backend: networking.IngressBackend{
|
||||
ServiceName: "http-svc-canary",
|
||||
ServicePort: intstr.IntOrString{
|
||||
|
@ -1165,7 +1163,7 @@ func TestGetBackendServers(t *testing.T) {
|
|||
Paths: []networking.HTTPIngressPath{
|
||||
{
|
||||
Path: "/a",
|
||||
PathType: &pathPrefix,
|
||||
PathType: &pathTypePrefix,
|
||||
Backend: networking.IngressBackend{
|
||||
ServiceName: "http-svc-1",
|
||||
ServicePort: intstr.IntOrString{
|
||||
|
@ -1202,7 +1200,7 @@ func TestGetBackendServers(t *testing.T) {
|
|||
Paths: []networking.HTTPIngressPath{
|
||||
{
|
||||
Path: "/a",
|
||||
PathType: &pathPrefix,
|
||||
PathType: &pathTypePrefix,
|
||||
Backend: networking.IngressBackend{
|
||||
ServiceName: "http-svc-2",
|
||||
ServicePort: intstr.IntOrString{
|
||||
|
@ -1239,7 +1237,7 @@ func TestGetBackendServers(t *testing.T) {
|
|||
Paths: []networking.HTTPIngressPath{
|
||||
{
|
||||
Path: "/b",
|
||||
PathType: &pathPrefix,
|
||||
PathType: &pathTypePrefix,
|
||||
Backend: networking.IngressBackend{
|
||||
ServiceName: "http-svc-2",
|
||||
ServicePort: intstr.IntOrString{
|
||||
|
@ -1276,7 +1274,7 @@ func TestGetBackendServers(t *testing.T) {
|
|||
Paths: []networking.HTTPIngressPath{
|
||||
{
|
||||
Path: "/b",
|
||||
PathType: &pathPrefix,
|
||||
PathType: &pathTypePrefix,
|
||||
Backend: networking.IngressBackend{
|
||||
ServiceName: "http-svc-1",
|
||||
ServicePort: intstr.IntOrString{
|
||||
|
@ -1313,7 +1311,7 @@ func TestGetBackendServers(t *testing.T) {
|
|||
Paths: []networking.HTTPIngressPath{
|
||||
{
|
||||
Path: "/c",
|
||||
PathType: &pathPrefix,
|
||||
PathType: &pathTypePrefix,
|
||||
Backend: networking.IngressBackend{
|
||||
ServiceName: "http-svc-1",
|
||||
ServicePort: intstr.IntOrString{
|
||||
|
@ -1350,7 +1348,7 @@ func TestGetBackendServers(t *testing.T) {
|
|||
Paths: []networking.HTTPIngressPath{
|
||||
{
|
||||
Path: "/c",
|
||||
PathType: &pathPrefix,
|
||||
PathType: &pathTypePrefix,
|
||||
Backend: networking.IngressBackend{
|
||||
ServiceName: "http-svc-2",
|
||||
ServicePort: intstr.IntOrString{
|
||||
|
@ -1435,7 +1433,7 @@ func TestGetBackendServers(t *testing.T) {
|
|||
Paths: []networking.HTTPIngressPath{
|
||||
{
|
||||
Path: "/path1",
|
||||
PathType: &pathPrefix,
|
||||
PathType: &pathTypePrefix,
|
||||
Backend: networking.IngressBackend{
|
||||
ServiceName: "path1-svc",
|
||||
ServicePort: intstr.IntOrString{
|
||||
|
@ -1475,7 +1473,7 @@ func TestGetBackendServers(t *testing.T) {
|
|||
Paths: []networking.HTTPIngressPath{
|
||||
{
|
||||
Path: "/path2",
|
||||
PathType: &pathPrefix,
|
||||
PathType: &pathTypePrefix,
|
||||
Backend: networking.IngressBackend{
|
||||
ServiceName: "path2-svc",
|
||||
ServicePort: intstr.IntOrString{
|
||||
|
@ -1540,7 +1538,7 @@ func TestGetBackendServers(t *testing.T) {
|
|||
Paths: []networking.HTTPIngressPath{
|
||||
{
|
||||
Path: "/path1",
|
||||
PathType: &pathPrefix,
|
||||
PathType: &pathTypePrefix,
|
||||
Backend: networking.IngressBackend{
|
||||
ServiceName: "path1-svc",
|
||||
ServicePort: intstr.IntOrString{
|
||||
|
@ -1580,7 +1578,7 @@ func TestGetBackendServers(t *testing.T) {
|
|||
Paths: []networking.HTTPIngressPath{
|
||||
{
|
||||
Path: "/path2",
|
||||
PathType: &pathPrefix,
|
||||
PathType: &pathTypePrefix,
|
||||
Backend: networking.IngressBackend{
|
||||
ServiceName: "path2-svc",
|
||||
ServicePort: intstr.IntOrString{
|
||||
|
|
112
internal/ingress/controller/location.go
Normal file
112
internal/ingress/controller/location.go
Normal file
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
Copyright 2020 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 controller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/mitchellh/copystructure"
|
||||
networking "k8s.io/api/networking/v1beta1"
|
||||
"k8s.io/ingress-nginx/internal/ingress"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
pathTypeExact = networking.PathTypeExact
|
||||
pathTypePrefix = networking.PathTypePrefix
|
||||
)
|
||||
|
||||
// updateServerLocations inspects the generated locations configuration for a server
|
||||
// normalizing the path and adding an additional exact location when is possible
|
||||
func updateServerLocations(locations []*ingress.Location) []*ingress.Location {
|
||||
newLocations := []*ingress.Location{}
|
||||
|
||||
// get Exact locations to check if one already exists
|
||||
exactLocations := map[string]*ingress.Location{}
|
||||
for _, location := range locations {
|
||||
if *location.PathType == pathTypeExact {
|
||||
exactLocations[location.Path] = location
|
||||
}
|
||||
}
|
||||
|
||||
for _, location := range locations {
|
||||
// location / does not require any update
|
||||
if location.Path == rootLocation {
|
||||
newLocations = append(newLocations, location)
|
||||
continue
|
||||
}
|
||||
|
||||
// only Prefix locations could require an additional location block
|
||||
if *location.PathType != pathTypePrefix {
|
||||
newLocations = append(newLocations, location)
|
||||
continue
|
||||
}
|
||||
|
||||
// locations with rewrite or using regular expressions are not modified
|
||||
if needsRewrite(location) || location.Rewrite.UseRegex {
|
||||
newLocations = append(newLocations, location)
|
||||
continue
|
||||
}
|
||||
|
||||
// If exists an Exact location is not possible to create a new one.
|
||||
if _, alreadyExists := exactLocations[location.Path]; alreadyExists {
|
||||
// normalize path. Must end in /
|
||||
location.Path = normalizePrefixPath(location.Path)
|
||||
newLocations = append(newLocations, location)
|
||||
continue
|
||||
}
|
||||
|
||||
// copy location before any change
|
||||
el, err := copystructure.Copy(location)
|
||||
if err != nil {
|
||||
klog.ErrorS(err, "copying location")
|
||||
}
|
||||
|
||||
// normalize path. Must end in /
|
||||
location.Path = normalizePrefixPath(location.Path)
|
||||
newLocations = append(newLocations, location)
|
||||
|
||||
// add exact location
|
||||
exactLocation := el.(*ingress.Location)
|
||||
exactLocation.PathType = &pathTypeExact
|
||||
|
||||
newLocations = append(newLocations, exactLocation)
|
||||
}
|
||||
|
||||
return newLocations
|
||||
}
|
||||
|
||||
func normalizePrefixPath(path string) string {
|
||||
if path == rootLocation {
|
||||
return rootLocation
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(path, "/") {
|
||||
return fmt.Sprintf("%v/", path)
|
||||
}
|
||||
|
||||
return path
|
||||
}
|
||||
|
||||
func needsRewrite(location *ingress.Location) bool {
|
||||
if len(location.Rewrite.Target) > 0 && location.Rewrite.Target != location.Path {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
|
@ -317,26 +317,16 @@ 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,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -417,7 +407,7 @@ func buildLocation(input interface{}, enforceRegex bool) string {
|
|||
}
|
||||
|
||||
if location.PathType != nil && *location.PathType == networkingv1beta1.PathTypeExact {
|
||||
return fmt.Sprintf(`~ ^%s$`, path)
|
||||
return fmt.Sprintf(`= %s`, path)
|
||||
}
|
||||
|
||||
return path
|
||||
|
|
|
@ -97,25 +97,6 @@ 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
|
||||
|
@ -128,12 +109,6 @@ 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
|
||||
|
|
|
@ -95,7 +95,8 @@ var _ = framework.DescribeAnnotation("rewrite-target use-regex enable-rewrite-lo
|
|||
|
||||
f.WaitForNginxServer(host,
|
||||
func(server string) bool {
|
||||
return strings.Contains(server, `location ~* "^/" {`) && strings.Contains(server, `location ~* "^/.well-known/acme/challenge" {`)
|
||||
return strings.Contains(server, `location ~* "^/" {`) &&
|
||||
strings.Contains(server, `location ~* "^/.well-known/acme/challenge" {`)
|
||||
})
|
||||
|
||||
ginkgo.By("making a second request to the non-rewritten location")
|
||||
|
@ -116,7 +117,7 @@ var _ = framework.DescribeAnnotation("rewrite-target use-regex enable-rewrite-lo
|
|||
|
||||
f.WaitForNginxServer(host,
|
||||
func(server string) bool {
|
||||
return strings.Contains(server, "location /foo {")
|
||||
return strings.Contains(server, "location /foo/ {")
|
||||
})
|
||||
|
||||
ginkgo.By(`creating an ingress definition with the use-regex amd rewrite-target annotation`)
|
||||
|
@ -129,7 +130,8 @@ var _ = framework.DescribeAnnotation("rewrite-target use-regex enable-rewrite-lo
|
|||
|
||||
f.WaitForNginxServer(host,
|
||||
func(server string) bool {
|
||||
return strings.Contains(server, `location ~* "^/foo" {`) && strings.Contains(server, `location ~* "^/foo.+" {`)
|
||||
return strings.Contains(server, `location ~* "^/foo" {`) &&
|
||||
strings.Contains(server, `location ~* "^/foo.+" {`)
|
||||
})
|
||||
|
||||
ginkgo.By("ensuring '/foo' matches '~* ^/foo'")
|
||||
|
|
|
@ -60,8 +60,8 @@ var _ = framework.IngressNginxDescribe("[Ingress] [PathType] exact", func() {
|
|||
f.WaitForNginxServer(host,
|
||||
func(server string) bool {
|
||||
return strings.Contains(server, host) &&
|
||||
strings.Contains(server, "location ~ ^/exact$") &&
|
||||
strings.Contains(server, "location /exact")
|
||||
strings.Contains(server, "location = /exact") &&
|
||||
strings.Contains(server, "location /exact/")
|
||||
})
|
||||
|
||||
body := f.HTTPTestClient().
|
||||
|
@ -98,8 +98,8 @@ var _ = framework.IngressNginxDescribe("[Ingress] [PathType] exact", func() {
|
|||
f.WaitForNginxServer(host,
|
||||
func(server string) bool {
|
||||
return strings.Contains(server, host) &&
|
||||
strings.Contains(server, "location ~ ^/exact$") &&
|
||||
strings.Contains(server, "location /exact")
|
||||
strings.Contains(server, "location = /exact") &&
|
||||
strings.Contains(server, "location /exact/")
|
||||
})
|
||||
|
||||
body = f.HTTPTestClient().
|
||||
|
|
149
test/e2e/ingress/pathtype_mixed.go
Normal file
149
test/e2e/ingress/pathtype_mixed.go
Normal file
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
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"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
networkingv1beta1 "k8s.io/api/networking/v1beta1"
|
||||
"k8s.io/ingress-nginx/test/e2e/framework"
|
||||
)
|
||||
|
||||
var _ = framework.IngressNginxDescribe("[Ingress] [PathType] mix Exact and Prefix paths", func() {
|
||||
f := framework.NewDefaultFramework("mixed")
|
||||
|
||||
ginkgo.BeforeEach(func() {
|
||||
f.NewEchoDeployment()
|
||||
})
|
||||
|
||||
var exactPathType = networkingv1beta1.PathTypeExact
|
||||
|
||||
ginkgo.It("should choose the correct location", func() {
|
||||
if !f.IsIngressV1Beta1Ready {
|
||||
ginkgo.Skip("Test requires Kubernetes v1.18 or higher")
|
||||
}
|
||||
|
||||
host := "mixed.path"
|
||||
|
||||
annotations := map[string]string{
|
||||
"nginx.ingress.kubernetes.io/configuration-snippet": `more_set_input_headers "pathType: exact";more_set_input_headers "pathlocation: /";`,
|
||||
}
|
||||
ing := framework.NewSingleIngress("exact-root", "/", host, f.Namespace, framework.EchoService, 80, annotations)
|
||||
ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].PathType = &exactPathType
|
||||
f.EnsureIngress(ing)
|
||||
|
||||
annotations = map[string]string{
|
||||
"nginx.ingress.kubernetes.io/configuration-snippet": `more_set_input_headers "pathType: prefix";more_set_input_headers "pathlocation: /";`,
|
||||
}
|
||||
ing = framework.NewSingleIngress("prefix-root", "/", host, f.Namespace, framework.EchoService, 80, annotations)
|
||||
f.EnsureIngress(ing)
|
||||
|
||||
f.WaitForNginxServer(host,
|
||||
func(server string) bool {
|
||||
return strings.Contains(server, host) &&
|
||||
strings.Contains(server, "location = /") &&
|
||||
strings.Contains(server, "location /")
|
||||
})
|
||||
|
||||
ginkgo.By("Checking exact request to /")
|
||||
body := f.HTTPTestClient().
|
||||
GET("/").
|
||||
WithHeader("Host", host).
|
||||
Expect().
|
||||
Status(http.StatusOK).
|
||||
Body().
|
||||
Raw()
|
||||
|
||||
assert.NotContains(ginkgo.GinkgoT(), body, "pathtype=prefix")
|
||||
assert.Contains(ginkgo.GinkgoT(), body, "pathtype=exact")
|
||||
assert.Contains(ginkgo.GinkgoT(), body, "pathlocation=/")
|
||||
|
||||
ginkgo.By("Checking prefix request to /bar")
|
||||
body = f.HTTPTestClient().
|
||||
GET("/bar").
|
||||
WithHeader("Host", host).
|
||||
Expect().
|
||||
Status(http.StatusOK).
|
||||
Body().
|
||||
Raw()
|
||||
|
||||
assert.Contains(ginkgo.GinkgoT(), body, "pathtype=prefix")
|
||||
assert.NotContains(ginkgo.GinkgoT(), body, "pathtype=exact")
|
||||
assert.Contains(ginkgo.GinkgoT(), body, "pathlocation=/")
|
||||
|
||||
annotations = map[string]string{
|
||||
"nginx.ingress.kubernetes.io/configuration-snippet": `more_set_input_headers "pathType: exact";more_set_input_headers "pathlocation: /foo";`,
|
||||
}
|
||||
ing = framework.NewSingleIngress("exact-foo", "/foo", host, f.Namespace, framework.EchoService, 80, annotations)
|
||||
ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].PathType = &exactPathType
|
||||
f.EnsureIngress(ing)
|
||||
|
||||
annotations = map[string]string{
|
||||
"nginx.ingress.kubernetes.io/configuration-snippet": `more_set_input_headers "pathType: prefix";more_set_input_headers "pathlocation: /foo";`,
|
||||
}
|
||||
ing = framework.NewSingleIngress("prefix-foo", "/foo", host, f.Namespace, framework.EchoService, 80, annotations)
|
||||
f.EnsureIngress(ing)
|
||||
|
||||
f.WaitForNginxServer(host,
|
||||
func(server string) bool {
|
||||
return strings.Contains(server, host) &&
|
||||
strings.Contains(server, "location = /foo") &&
|
||||
strings.Contains(server, "location /foo/")
|
||||
})
|
||||
|
||||
ginkgo.By("Checking exact request to /foo")
|
||||
body = f.HTTPTestClient().
|
||||
GET("/foo").
|
||||
WithHeader("Host", host).
|
||||
Expect().
|
||||
Status(http.StatusOK).
|
||||
Body().
|
||||
Raw()
|
||||
|
||||
assert.NotContains(ginkgo.GinkgoT(), body, "pathtype=prefix")
|
||||
assert.Contains(ginkgo.GinkgoT(), body, "pathtype=exact")
|
||||
assert.Contains(ginkgo.GinkgoT(), body, "pathlocation=/foo")
|
||||
|
||||
ginkgo.By("Checking prefix request to /foo/bar")
|
||||
body = f.HTTPTestClient().
|
||||
GET("/foo/bar").
|
||||
WithHeader("Host", host).
|
||||
Expect().
|
||||
Status(http.StatusOK).
|
||||
Body().
|
||||
Raw()
|
||||
|
||||
assert.Contains(ginkgo.GinkgoT(), body, "pathtype=prefix")
|
||||
assert.Contains(ginkgo.GinkgoT(), body, "pathlocation=/foo")
|
||||
|
||||
ginkgo.By("Checking prefix request to /foobar")
|
||||
body = f.HTTPTestClient().
|
||||
GET("/foobar").
|
||||
WithHeader("Host", host).
|
||||
Expect().
|
||||
Status(http.StatusOK).
|
||||
Body().
|
||||
Raw()
|
||||
|
||||
assert.Contains(ginkgo.GinkgoT(), body, "pathtype=prefix")
|
||||
assert.Contains(ginkgo.GinkgoT(), body, "pathlocation=/")
|
||||
})
|
||||
})
|
Loading…
Reference in a new issue