Skip to content

Commit b2d078b

Browse files
authored
fix: Ensure unique generated locations (#1445)
Problem: As a user, I want to ensure internal location blocks are not named the same as other defined location blocks. Solution: Removed prefix name for internal location blocks, and gave an indexed name to avoid collision with other location blocks. Updated unit tests and cleaned up unused fields tracking `internal` location blocks.
1 parent 9dc786a commit b2d078b

File tree

8 files changed

+40
-108
lines changed

8 files changed

+40
-108
lines changed

internal/mode/static/nginx/config/http/config.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ type Location struct {
1818
ProxyPass string
1919
HTTPMatchVar string
2020
ProxySetHeaders []Header
21-
Internal bool
2221
}
2322

2423
// Header defines a HTTP header to be passed to the proxied server.

internal/mode/static/nginx/config/servers.go

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -95,18 +95,16 @@ func createServer(virtualServer dataplane.VirtualServer) http.Server {
9595
// rewriteConfig contains the configuration for a location to rewrite paths,
9696
// as specified in a URLRewrite filter
9797
type rewriteConfig struct {
98-
// InternalRewrite rewrites an internal URI to the original URI (ex: /coffee_prefix_route0 -> /coffee)
99-
InternalRewrite string
100-
// MainRewrite rewrites the original URI to the new URI (ex: /coffee -> /beans)
101-
MainRewrite string
98+
// Rewrite rewrites the original URI to the new URI (ex: /coffee -> /beans)
99+
Rewrite string
102100
}
103101

104102
func createLocations(pathRules []dataplane.PathRule, listenerPort int32) []http.Location {
105103
maxLocs, pathsAndTypes := getMaxLocationCountAndPathMap(pathRules)
106104
locs := make([]http.Location, 0, maxLocs)
107105
var rootPathExists bool
108106

109-
for _, rule := range pathRules {
107+
for pathRuleIdx, rule := range pathRules {
110108
matches := make([]httpMatch, 0, len(rule.MatchRules))
111109

112110
if rule.Path == rootPath {
@@ -118,7 +116,7 @@ func createLocations(pathRules []dataplane.PathRule, listenerPort int32) []http.
118116
for matchRuleIdx, r := range rule.MatchRules {
119117
buildLocations := extLocations
120118
if len(rule.MatchRules) != 1 || !isPathOnlyMatch(r.Match) {
121-
intLocation, match := initializeInternalLocation(rule, matchRuleIdx, r.Match)
119+
intLocation, match := initializeInternalLocation(pathRuleIdx, matchRuleIdx, r.Match)
122120
buildLocations = []http.Location{intLocation}
123121
matches = append(matches, match)
124122
}
@@ -216,11 +214,11 @@ func initializeExternalLocations(
216214
}
217215

218216
func initializeInternalLocation(
219-
rule dataplane.PathRule,
217+
pathruleIdx,
220218
matchRuleIdx int,
221219
match dataplane.Match,
222220
) (http.Location, httpMatch) {
223-
path := createPathForMatch(rule.Path, rule.PathType, matchRuleIdx)
221+
path := fmt.Sprintf("@rule%d-route%d", pathruleIdx, matchRuleIdx)
224222
return createMatchLocation(path), createHTTPMatch(match, path)
225223
}
226224

@@ -252,11 +250,8 @@ func updateLocationsForFilters(
252250
proxyPass := createProxyPass(matchRule.BackendGroup, matchRule.Filters.RequestURLRewrite)
253251
for i := range buildLocations {
254252
if rewrites != nil {
255-
if buildLocations[i].Internal && rewrites.InternalRewrite != "" {
256-
buildLocations[i].Rewrites = append(buildLocations[i].Rewrites, rewrites.InternalRewrite)
257-
}
258-
if rewrites.MainRewrite != "" {
259-
buildLocations[i].Rewrites = append(buildLocations[i].Rewrites, rewrites.MainRewrite)
253+
if rewrites.Rewrite != "" {
254+
buildLocations[i].Rewrites = append(buildLocations[i].Rewrites, rewrites.Rewrite)
260255
}
261256
}
262257
buildLocations[i].ProxySetHeaders = proxySetHeaders
@@ -319,10 +314,9 @@ func createRewritesValForRewriteFilter(filter *dataplane.HTTPURLRewriteFilter, p
319314
rewrites := &rewriteConfig{}
320315

321316
if filter.Path != nil {
322-
rewrites.InternalRewrite = "^ $request_uri"
323317
switch filter.Path.Type {
324318
case dataplane.ReplaceFullPath:
325-
rewrites.MainRewrite = fmt.Sprintf("^ %s break", filter.Path.Replacement)
319+
rewrites.Rewrite = fmt.Sprintf("^ %s break", filter.Path.Replacement)
326320
case dataplane.ReplacePrefixMatch:
327321
filterPrefix := filter.Path.Replacement
328322
if filterPrefix == "" {
@@ -347,7 +341,7 @@ func createRewritesValForRewriteFilter(filter *dataplane.HTTPURLRewriteFilter, p
347341
replacement = fmt.Sprintf("%s/$1", filterPrefix)
348342
}
349343

350-
rewrites.MainRewrite = fmt.Sprintf("%s %s break", regex, replacement)
344+
rewrites.Rewrite = fmt.Sprintf("%s %s break", regex, replacement)
351345
}
352346
}
353347

@@ -449,8 +443,7 @@ func createProxyPass(backendGroup dataplane.BackendGroup, filter *dataplane.HTTP
449443

450444
func createMatchLocation(path string) http.Location {
451445
return http.Location{
452-
Path: path,
453-
Internal: true,
446+
Path: path,
454447
}
455448
}
456449

@@ -544,10 +537,6 @@ func createPath(rule dataplane.PathRule) string {
544537
}
545538
}
546539

547-
func createPathForMatch(path string, pathType dataplane.PathType, routeIdx int) string {
548-
return fmt.Sprintf("%s_%s_route%d", path, pathType, routeIdx)
549-
}
550-
551540
func createDefaultRootLocation() http.Location {
552541
return http.Location{
553542
Path: "/",

internal/mode/static/nginx/config/servers_template.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,6 @@ server {
3333
3434
{{ range $l := $s.Locations }}
3535
location {{ $l.Path }} {
36-
{{ if $l.Internal -}}
37-
internal;
38-
{{ end }}
39-
4036
{{- range $r := $l.Rewrites }}
4137
rewrite {{ $r }};
4238
{{- end }}

internal/mode/static/nginx/config/servers_test.go

Lines changed: 25 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -490,34 +490,34 @@ func TestCreateServers(t *testing.T) {
490490
}
491491

492492
slashMatches := []httpMatch{
493-
{Method: "POST", RedirectPath: "/_prefix_route0"},
494-
{Method: "PATCH", RedirectPath: "/_prefix_route1"},
495-
{Any: true, RedirectPath: "/_prefix_route2"},
493+
{Method: "POST", RedirectPath: "@rule0-route0"},
494+
{Method: "PATCH", RedirectPath: "@rule0-route1"},
495+
{Any: true, RedirectPath: "@rule0-route2"},
496496
}
497497
testMatches := []httpMatch{
498498
{
499499
Method: "GET",
500500
Headers: []string{"Version:V1", "test:foo", "my-header:my-value"},
501501
QueryParams: []string{"GrEat=EXAMPLE", "test=foo=bar"},
502-
RedirectPath: "/test_prefix_route0",
502+
RedirectPath: "@rule1-route0",
503503
},
504504
}
505505
exactMatches := []httpMatch{
506506
{
507507
Method: "GET",
508-
RedirectPath: "/test_exact_route0",
508+
RedirectPath: "@rule11-route0",
509509
},
510510
}
511511
redirectHeaderMatches := []httpMatch{
512512
{
513513
Headers: []string{"redirect:this"},
514-
RedirectPath: "/redirect-with-headers_prefix_route0",
514+
RedirectPath: "@rule5-route0",
515515
},
516516
}
517517
rewriteHeaderMatches := []httpMatch{
518518
{
519519
Headers: []string{"rewrite:this"},
520-
RedirectPath: "/rewrite-with-headers_prefix_route0",
520+
RedirectPath: "@rule7-route0",
521521
},
522522
}
523523
rewriteProxySetHeaders := []http.Header{
@@ -541,7 +541,7 @@ func TestCreateServers(t *testing.T) {
541541
invalidFilterHeaderMatches := []httpMatch{
542542
{
543543
Headers: []string{"filter:this"},
544-
RedirectPath: "/invalid-filter-with-headers_prefix_route0",
544+
RedirectPath: "@rule9-route0",
545545
},
546546
}
547547

@@ -553,20 +553,17 @@ func TestCreateServers(t *testing.T) {
553553

554554
return []http.Location{
555555
{
556-
Path: "/_prefix_route0",
557-
Internal: true,
556+
Path: "@rule0-route0",
558557
ProxyPass: "http://test_foo_80$request_uri",
559558
ProxySetHeaders: baseHeaders,
560559
},
561560
{
562-
Path: "/_prefix_route1",
563-
Internal: true,
561+
Path: "@rule0-route1",
564562
ProxyPass: "http://test_foo_80$request_uri",
565563
ProxySetHeaders: baseHeaders,
566564
},
567565
{
568-
Path: "/_prefix_route2",
569-
Internal: true,
566+
Path: "@rule0-route2",
570567
ProxyPass: "http://test_foo_80$request_uri",
571568
ProxySetHeaders: baseHeaders,
572569
},
@@ -575,8 +572,7 @@ func TestCreateServers(t *testing.T) {
575572
HTTPMatchVar: expectedMatchString(slashMatches),
576573
},
577574
{
578-
Path: "/test_prefix_route0",
579-
Internal: true,
575+
Path: "@rule1-route0",
580576
ProxyPass: "http://$test__route1_rule1$request_uri",
581577
ProxySetHeaders: baseHeaders,
582578
},
@@ -623,12 +619,11 @@ func TestCreateServers(t *testing.T) {
623619
},
624620
},
625621
{
626-
Path: "/redirect-with-headers_prefix_route0",
622+
Path: "@rule5-route0",
627623
Return: &http.Return{
628624
Body: "$scheme://foo.example.com:8080$request_uri",
629625
Code: 302,
630626
},
631-
Internal: true,
632627
},
633628
{
634629
Path: "/redirect-with-headers/",
@@ -651,9 +646,8 @@ func TestCreateServers(t *testing.T) {
651646
ProxySetHeaders: rewriteProxySetHeaders,
652647
},
653648
{
654-
Path: "/rewrite-with-headers_prefix_route0",
655-
Rewrites: []string{"^ $request_uri", "^/rewrite-with-headers(.*)$ /prefix-replacement$1 break"},
656-
Internal: true,
649+
Path: "@rule7-route0",
650+
Rewrites: []string{"^/rewrite-with-headers(.*)$ /prefix-replacement$1 break"},
657651
ProxyPass: "http://test_foo_80",
658652
ProxySetHeaders: rewriteProxySetHeaders,
659653
},
@@ -678,11 +672,10 @@ func TestCreateServers(t *testing.T) {
678672
},
679673
},
680674
{
681-
Path: "/invalid-filter-with-headers_prefix_route0",
675+
Path: "@rule9-route0",
682676
Return: &http.Return{
683677
Code: http.StatusInternalServerError,
684678
},
685-
Internal: true,
686679
},
687680
{
688681
Path: "/invalid-filter-with-headers/",
@@ -698,10 +691,9 @@ func TestCreateServers(t *testing.T) {
698691
ProxySetHeaders: baseHeaders,
699692
},
700693
{
701-
Path: "/test_exact_route0",
694+
Path: "@rule11-route0",
702695
ProxyPass: "http://test_foo_80$request_uri",
703696
ProxySetHeaders: baseHeaders,
704-
Internal: true,
705697
},
706698
{
707699
Path: "= /test",
@@ -1274,8 +1266,7 @@ func TestCreateRewritesValForRewriteFilter(t *testing.T) {
12741266
},
12751267
},
12761268
expected: &rewriteConfig{
1277-
InternalRewrite: "^ $request_uri",
1278-
MainRewrite: "^ /full-path break",
1269+
Rewrite: "^ /full-path break",
12791270
},
12801271
msg: "full path",
12811272
},
@@ -1288,8 +1279,7 @@ func TestCreateRewritesValForRewriteFilter(t *testing.T) {
12881279
},
12891280
},
12901281
expected: &rewriteConfig{
1291-
InternalRewrite: "^ $request_uri",
1292-
MainRewrite: "^/original(.*)$ /prefix-path$1 break",
1282+
Rewrite: "^/original(.*)$ /prefix-path$1 break",
12931283
},
12941284
msg: "prefix path no trailing slashes",
12951285
},
@@ -1302,8 +1292,7 @@ func TestCreateRewritesValForRewriteFilter(t *testing.T) {
13021292
},
13031293
},
13041294
expected: &rewriteConfig{
1305-
InternalRewrite: "^ $request_uri",
1306-
MainRewrite: "^/original(?:/(.*))?$ /$1 break",
1295+
Rewrite: "^/original(?:/(.*))?$ /$1 break",
13071296
},
13081297
msg: "prefix path empty string",
13091298
},
@@ -1316,8 +1305,7 @@ func TestCreateRewritesValForRewriteFilter(t *testing.T) {
13161305
},
13171306
},
13181307
expected: &rewriteConfig{
1319-
InternalRewrite: "^ $request_uri",
1320-
MainRewrite: "^/original(?:/(.*))?$ /$1 break",
1308+
Rewrite: "^/original(?:/(.*))?$ /$1 break",
13211309
},
13221310
msg: "prefix path /",
13231311
},
@@ -1330,8 +1318,7 @@ func TestCreateRewritesValForRewriteFilter(t *testing.T) {
13301318
},
13311319
},
13321320
expected: &rewriteConfig{
1333-
InternalRewrite: "^ $request_uri",
1334-
MainRewrite: "^/original(?:/(.*))?$ /trailing/$1 break",
1321+
Rewrite: "^/original(?:/(.*))?$ /trailing/$1 break",
13351322
},
13361323
msg: "prefix path replacement with trailing /",
13371324
},
@@ -1344,8 +1331,7 @@ func TestCreateRewritesValForRewriteFilter(t *testing.T) {
13441331
},
13451332
},
13461333
expected: &rewriteConfig{
1347-
InternalRewrite: "^ $request_uri",
1348-
MainRewrite: "^/original/(.*)$ /prefix-path/$1 break",
1334+
Rewrite: "^/original/(.*)$ /prefix-path/$1 break",
13491335
},
13501336
msg: "prefix path original with trailing /",
13511337
},
@@ -1358,8 +1344,7 @@ func TestCreateRewritesValForRewriteFilter(t *testing.T) {
13581344
},
13591345
},
13601346
expected: &rewriteConfig{
1361-
InternalRewrite: "^ $request_uri",
1362-
MainRewrite: "^/original/(.*)$ /trailing/$1 break",
1347+
Rewrite: "^/original/(.*)$ /trailing/$1 break",
13631348
},
13641349
msg: "prefix path both with trailing slashes",
13651350
},
@@ -1694,38 +1679,13 @@ func TestCreateMatchLocation(t *testing.T) {
16941679
g := NewWithT(t)
16951680

16961681
expected := http.Location{
1697-
Path: "/path",
1698-
Internal: true,
1682+
Path: "/path",
16991683
}
17001684

17011685
result := createMatchLocation("/path")
17021686
g.Expect(result).To(Equal(expected))
17031687
}
17041688

1705-
func TestCreatePathForMatch(t *testing.T) {
1706-
g := NewWithT(t)
1707-
1708-
tests := []struct {
1709-
expected string
1710-
pathType dataplane.PathType
1711-
panic bool
1712-
}{
1713-
{
1714-
expected: "/path_prefix_route1",
1715-
pathType: dataplane.PathTypePrefix,
1716-
},
1717-
{
1718-
expected: "/path_exact_route1",
1719-
pathType: dataplane.PathTypeExact,
1720-
},
1721-
}
1722-
1723-
for _, tc := range tests {
1724-
result := createPathForMatch("/path", tc.pathType, 1)
1725-
g.Expect(result).To(Equal(tc.expected))
1726-
}
1727-
}
1728-
17291689
func TestGenerateProxySetHeaders(t *testing.T) {
17301690
tests := []struct {
17311691
filters *dataplane.HTTPFilters

internal/mode/static/nginx/config/validation/http_njs_match.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,7 @@ func (HTTPNJSMatchValidator) ValidatePathInMatch(path string) error {
2626
return errors.New(msg)
2727
}
2828

29-
// FIXME(pleshakov): This function will no longer be
30-
// needed once https://github.com/nginxinc/nginx-gateway-fabric/issues/428 is fixed.
31-
// That's because the location path gets into the set directive in the location block.
32-
// Example: set $http_matches "[{\"redirectPath\":\"/coffee_route0\" ...
33-
// Where /coffee is tha path.
34-
return validateCommonNJSMatchPart(path)
29+
return nil
3530
}
3631

3732
func (HTTPNJSMatchValidator) ValidateHeaderNameInMatch(name string) error {

internal/mode/static/nginx/config/validation/http_njs_match_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ func TestValidatePathInMatch(t *testing.T) {
1313
"/",
1414
"/path",
1515
"/path/subpath-123",
16+
"/route0-rule0",
1617
)
1718
testInvalidValuesForSimpleValidator(
1819
t,
@@ -23,7 +24,6 @@ func TestValidatePathInMatch(t *testing.T) {
2324
"/path;",
2425
"path",
2526
"",
26-
"/path$",
2727
)
2828
}
2929

0 commit comments

Comments
 (0)