Make the behavior of prefix matching in Ingress consistent with Kubernetes doc
This commit is contained in:
parent
8c6ed23c5f
commit
4790e4910f
10 changed files with 262 additions and 2 deletions
|
|
@ -3,7 +3,10 @@ package ingress
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
|
@ -14,6 +17,7 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
ptypes "github.com/traefik/paerser/types"
|
||||
"github.com/traefik/traefik/v3/pkg/config/dynamic"
|
||||
traefikhttp "github.com/traefik/traefik/v3/pkg/muxer/http"
|
||||
"github.com/traefik/traefik/v3/pkg/provider"
|
||||
"github.com/traefik/traefik/v3/pkg/provider/kubernetes/k8s"
|
||||
"github.com/traefik/traefik/v3/pkg/tls"
|
||||
|
|
@ -38,6 +42,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
|||
disableIngressClassLookup bool
|
||||
disableClusterScopeResources bool
|
||||
defaultRuleSyntax string
|
||||
strictPrefixMatching bool
|
||||
}{
|
||||
{
|
||||
desc: "Empty ingresses",
|
||||
|
|
@ -1621,6 +1626,40 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "Ingress with strict prefix matching",
|
||||
expected: &dynamic.Configuration{
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
Middlewares: map[string]*dynamic.Middleware{},
|
||||
Routers: map[string]*dynamic.Router{
|
||||
"testing-bar": {
|
||||
Rule: "(Path(`/bar`) || PathPrefix(`/bar/`))",
|
||||
Service: "testing-service1-80",
|
||||
},
|
||||
},
|
||||
Services: map[string]*dynamic.Service{
|
||||
"testing-service1-80": {
|
||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||
Strategy: dynamic.BalancerStrategyWRR,
|
||||
PassHostHeader: pointer(true),
|
||||
ResponseForwarding: &dynamic.ResponseForwarding{
|
||||
FlushInterval: ptypes.Duration(100 * time.Millisecond),
|
||||
},
|
||||
Servers: []dynamic.Server{
|
||||
{
|
||||
URL: "http://10.10.0.1:8080",
|
||||
},
|
||||
{
|
||||
URL: "http://10.21.0.1:8080",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
strictPrefixMatching: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
|
|
@ -1634,6 +1673,7 @@ func TestLoadConfigurationFromIngresses(t *testing.T) {
|
|||
DisableIngressClassLookup: test.disableIngressClassLookup,
|
||||
DisableClusterScopeResources: test.disableClusterScopeResources,
|
||||
DefaultRuleSyntax: test.defaultRuleSyntax,
|
||||
StrictPrefixMatching: test.strictPrefixMatching,
|
||||
}
|
||||
conf := p.loadConfigurationFromIngresses(context.Background(), clientMock)
|
||||
|
||||
|
|
@ -2256,3 +2296,106 @@ func readResources(t *testing.T, paths []string) []runtime.Object {
|
|||
|
||||
return k8sObjects
|
||||
}
|
||||
|
||||
func TestStrictPrefixMatchingRule(t *testing.T) {
|
||||
tests := []struct {
|
||||
path string
|
||||
requestPath string
|
||||
match bool
|
||||
}{ // The tests are taken from https://kubernetes.io/docs/concepts/services-networking/ingress/#examples
|
||||
{
|
||||
path: "/foo",
|
||||
requestPath: "/foo",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
path: "/foo",
|
||||
requestPath: "/foo/",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
path: "/foo/",
|
||||
requestPath: "/foo",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
path: "/foo/",
|
||||
requestPath: "/foo/",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
path: "/aaa/bb",
|
||||
requestPath: "/aaa/bbb",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
path: "/aaa/bbb",
|
||||
requestPath: "/aaa/bbb",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
path: "/aaa/bbb/",
|
||||
requestPath: "/aaa/bbb",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
path: "/aaa/bbb",
|
||||
requestPath: "/aaa/bbb/",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
path: "/aaa/bbb",
|
||||
requestPath: "/aaa/bbb/ccc",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
path: "/aaa/bbb",
|
||||
requestPath: "/aaa/bbbxyz",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
path: "/",
|
||||
requestPath: "/aaa/ccc",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
path: "/aaa",
|
||||
requestPath: "/aaa/ccc",
|
||||
match: true,
|
||||
},
|
||||
{
|
||||
path: "/...",
|
||||
requestPath: "/aaa",
|
||||
match: false,
|
||||
},
|
||||
{
|
||||
path: "/...",
|
||||
requestPath: "/.../",
|
||||
match: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(fmt.Sprintf("Prefix match case %s", tt.path), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
|
||||
muxer, err := traefikhttp.NewMuxer()
|
||||
require.NoError(t, err)
|
||||
|
||||
rule := buildStrictPrefixMatchingRule(tt.path)
|
||||
err = muxer.AddRoute(rule, "", 0, handler)
|
||||
require.NoError(t, err)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
req := httptest.NewRequest(http.MethodGet, tt.requestPath, http.NoBody)
|
||||
muxer.ServeHTTP(w, req)
|
||||
|
||||
if tt.match {
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
} else {
|
||||
assert.Equal(t, http.StatusNotFound, w.Code)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue