Skip to content

Commit

Permalink
fix rewrite path for prefix match
Browse files Browse the repository at this point in the history
  • Loading branch information
salonichf5 committed Dec 23, 2024
1 parent 938b7ff commit 70366fe
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 13 deletions.
14 changes: 8 additions & 6 deletions internal/mode/static/nginx/config/servers.go
Original file line number Diff line number Diff line change
Expand Up @@ -620,22 +620,24 @@ func createRewritesValForRewriteFilter(filter *dataplane.HTTPURLRewriteFilter, p
filterPrefix = "/"
}

// capture everything after the configured prefix
regex := fmt.Sprintf("^%s(.*)$", path)
// replace the configured prefix with the filter prefix and append what was captured
replacement := fmt.Sprintf("%s$1", filterPrefix)
// capture everything after the configured prefix up to the first ? (if present)
regex := fmt.Sprintf("^%s([^?]*)?", path)
// replace the configured prefix with the filter prefix, append the captured segment,
// and include the request arguments stored in nginx variable $args
// (see: https://nginx.org/en/docs/http/ngx_http_core_module.html#var_args).
replacement := fmt.Sprintf("%s$1?$args?", filterPrefix)

// if configured prefix does not end in /, but replacement prefix does end in /,
// then make sure that we *require* but *don't capture* a trailing slash in the request,
// otherwise we'll get duplicate slashes in the full replacement
if strings.HasSuffix(filterPrefix, "/") && !strings.HasSuffix(path, "/") {
regex = fmt.Sprintf("^%s(?:/(.*))?$", path)
regex = fmt.Sprintf("^%s(?:/([^?]*))?", path)
}

// if configured prefix ends in / we won't capture it for a request (since it's not in the regex),
// so append it to the replacement prefix if the replacement prefix doesn't already end in /
if strings.HasSuffix(path, "/") && !strings.HasSuffix(filterPrefix, "/") {
replacement = fmt.Sprintf("%s/$1", filterPrefix)
replacement = fmt.Sprintf("%s/$1?$args?", filterPrefix)
}

rewrites.MainRewrite = fmt.Sprintf("%s %s break", regex, replacement)
Expand Down
14 changes: 7 additions & 7 deletions internal/mode/static/nginx/config/servers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1278,7 +1278,7 @@ func TestCreateServers(t *testing.T) {
},
{
Path: "/_ngf-internal-rule8-route0",
Rewrites: []string{"^ $request_uri", "^/rewrite-with-headers(.*)$ /prefix-replacement$1 break"},
Rewrites: []string{"^ $request_uri", "^/rewrite-with-headers([^?]*)? /prefix-replacement$1?$args? break"},
ProxyPass: "http://test_foo_80",
ProxySetHeaders: rewriteProxySetHeaders,
Type: http.InternalLocationType,
Expand Down Expand Up @@ -2441,7 +2441,7 @@ func TestCreateRewritesValForRewriteFilter(t *testing.T) {
},
expected: &rewriteConfig{
InternalRewrite: "^ $request_uri",
MainRewrite: "^/original(.*)$ /prefix-path$1 break",
MainRewrite: "^/original([^?]*)? /prefix-path$1?$args? break",
},
msg: "prefix path no trailing slashes",
},
Expand All @@ -2455,7 +2455,7 @@ func TestCreateRewritesValForRewriteFilter(t *testing.T) {
},
expected: &rewriteConfig{
InternalRewrite: "^ $request_uri",
MainRewrite: "^/original(?:/(.*))?$ /$1 break",
MainRewrite: "^/original(?:/([^?]*))? /$1?$args? break",
},
msg: "prefix path empty string",
},
Expand All @@ -2469,7 +2469,7 @@ func TestCreateRewritesValForRewriteFilter(t *testing.T) {
},
expected: &rewriteConfig{
InternalRewrite: "^ $request_uri",
MainRewrite: "^/original(?:/(.*))?$ /$1 break",
MainRewrite: "^/original(?:/([^?]*))? /$1?$args? break",
},
msg: "prefix path /",
},
Expand All @@ -2483,7 +2483,7 @@ func TestCreateRewritesValForRewriteFilter(t *testing.T) {
},
expected: &rewriteConfig{
InternalRewrite: "^ $request_uri",
MainRewrite: "^/original(?:/(.*))?$ /trailing/$1 break",
MainRewrite: "^/original(?:/([^?]*))? /trailing/$1?$args? break",
},
msg: "prefix path replacement with trailing /",
},
Expand All @@ -2497,7 +2497,7 @@ func TestCreateRewritesValForRewriteFilter(t *testing.T) {
},
expected: &rewriteConfig{
InternalRewrite: "^ $request_uri",
MainRewrite: "^/original/(.*)$ /prefix-path/$1 break",
MainRewrite: "^/original/([^?]*)? /prefix-path/$1?$args? break",
},
msg: "prefix path original with trailing /",
},
Expand All @@ -2511,7 +2511,7 @@ func TestCreateRewritesValForRewriteFilter(t *testing.T) {
},
expected: &rewriteConfig{
InternalRewrite: "^ $request_uri",
MainRewrite: "^/original/(.*)$ /trailing/$1 break",
MainRewrite: "^/original/([^?]*)? /trailing/$1?$args? break",
},
msg: "prefix path both with trailing slashes",
},
Expand Down
23 changes: 23 additions & 0 deletions site/content/how-to/traffic-management/redirects-and-rewrites.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,17 @@ Server name: coffee-6b8b6d6486-7fc78
URI: /beans
```

```shell
curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/coffee/mocha\?test\=v1\&test\=v2
```

```text
Server address: 10.244.0.235:8080
Server name: coffee-6db967495b-twn6x
...
URI: /beans?test=v1&test=v2
```

```shell
curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/latte/prices
```
Expand All @@ -199,6 +210,18 @@ Server name: coffee-6b8b6d6486-7fc78
URI: /prices
```

```shell
curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/latte/prices\?test\=v1\&test\=v2
```

```text
curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/latte/prices\?test\=v1\&test\=v2
Server address: 10.244.0.235:8080
Server name: coffee-6db967495b-twn6x
...
URI: /prices?test=v1&test=v2
```

## Further reading

To learn more about redirects and rewrites using the Gateway API, see the following resource:
Expand Down

0 comments on commit 70366fe

Please sign in to comment.