Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upstream is forwarding the decoded url (instead of the original url) while proxying requests #2105

Closed
deshah04 opened this issue May 3, 2023 · 2 comments
Labels

Comments

@deshah04
Copy link

deshah04 commented May 3, 2023

Upstream is forwarding the decoded url (instead of the original url) while proxying requests
I have the following upstream config:

upstreamConfig:
  upstreams:
  - flushInterval: 1s
    id: /
    passHostHeader: false
    path: ^/app/prefix/(.*)$
    rewriteTarget: /$1
    insecureSkipTLSVerify: true
    uri: https://host

The following request:
"https://host/app/prefix/v1/id/data%3Aabc%2Fdef "
is decoded to "https://host/v1/id/data:abc/def" , and then forwarded to upstream.

The issue is that "data%3Aabc%2Fdef " is the value of the id. But because it has been decoded, "/" is not interpreted as part of the value.

Expected Behavior

After URL is rewritten based on the upstream rules, the url need to be forwarded to the upstream without decoding the original URL.

Based on the above upstream config, the incoming url "https://host/app/prefix/v1/id/data%3Aabc%2Fdef" should be forwarded to
"https://host/v1/id/data%3Aabc%2Fdef "

Currently, it is decoding, and then forwarding to "https://host/v1/id/data:abc/def "

Possible Solution

Setting "proxyRAWPath" to true in the upstream config did not fix the issue - ( #997)

I had to change the rewrite code logic to also rewrite reqURL.RawPath.

diff --git a/pkg/upstream/rewrite.go b/pkg/upstream/rewrite.go
index a84e18c..c93a254 100644
--- a/pkg/upstream/rewrite.go
+++ b/pkg/upstream/rewrite.go
@@ -49,6 +49,10 @@ func rewritePath(rewriteRegExp *regexp.Regexp, rewriteTarget string, writer page
                        return
                }

+               newRawURI := rewriteRegExp.ReplaceAllString(reqURL.RawPath, rewriteTarget)
+               s := strings.SplitN(newRawURI, "?", 2)
+               reqURL.RawPath = s[0]
+
                req.RequestURI = reqURL.String()
                next.ServeHTTP(rw, req)
        })

If this is not done then reqURL.Path = "/v1/id/data:abc/def " and reqURLPath.RawPath = "/app/prefix/v1/id/data%3Aabc%2Fdef".

Because of this difference in which RawPath is not rewritten, EscapedPath() (called from url String()) does not return u.RawPath. The function escape(u.Path, encodePath) only escapes ? parameter, and hence req.RequestURI is set to the decoded value, and forwarded upstream.

func (u *URL) EscapedPath() string {
	if u.RawPath != "" && validEncoded(u.RawPath, encodePath) {
		p, err := unescape(u.RawPath, encodePath)
		if err == nil && p == u.Path {
			return u.RawPath
		}
	}
	if u.Path == "*" {
		return "*" // don't escape (Issue 11202)
	}
	return escape(u.Path, encodePath)
}

The above fix works fine.
Appreciate if this can be fixed in the next version. Not sure if another flag need to be introduced , or if we could re-use proxyRAWPath for this behavior, or if there is a different way of fixing it.

Your Environment

  • Version used: v7.4.0 (latest)
@github-actions
Copy link
Contributor

github-actions bot commented Jul 3, 2023

This issue has been inactive for 60 days. If the issue is still relevant please comment to re-activate the issue. If no action is taken within 7 days, the issue will be marked closed.

@github-actions github-actions bot added the Stale label Jul 3, 2023
@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Jul 11, 2023
@JoelSpeed
Copy link
Member

Sounds like we introduced a regression, if you want to fix the proxyRawPath option then a PR would be welcome

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants