From 95b8c2e98a93cc84dcf58a89c78c1f44cfe4d594 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Tue, 7 May 2024 13:57:41 +0800 Subject: [PATCH] improve --- modules/httplib/url.go | 26 +++++++++++--------------- modules/httplib/url_test.go | 3 ++- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/modules/httplib/url.go b/modules/httplib/url.go index d5ecb7f38d..541c4f325b 100644 --- a/modules/httplib/url.go +++ b/modules/httplib/url.go @@ -32,7 +32,7 @@ func IsRelativeURL(s string) bool { return err == nil && urlIsRelative(s, u) } -func guessRequestScheme(req *http.Request) string { +func guessRequestScheme(req *http.Request, def string) string { // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto if s := req.Header.Get("X-Forwarded-Proto"); s != "" { return s @@ -49,21 +49,12 @@ func guessRequestScheme(req *http.Request) string { if s := req.Header.Get("X-Forwarded-Ssl"); s != "" { return util.Iif(s == "on", "https", "http") } - if req.TLS != nil { - return "https" - } - return "http" + return def } -func guessRequestHost(req *http.Request) string { +func guessForwardedHost(req *http.Request) string { // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Host - if s := req.Header.Get("X-Forwarded-Host"); s != "" { - return s - } - if req.Host != "" { - return req.Host // Golang: the Host header is promoted to the Request.Host field and removed from the Header map. - } - return "" + return req.Header.Get("X-Forwarded-Host") } // GuessCurrentAppURL tries to guess the current full URL by http headers. It always has a '/' suffix, exactly the same as setting.AppURL @@ -72,8 +63,13 @@ func GuessCurrentAppURL(ctx context.Context) string { if !ok { return setting.AppURL } - if host := guessRequestHost(req); host != "" { - return guessRequestScheme(req) + "://" + host + setting.AppSubURL + "/" + if host := guessForwardedHost(req); host != "" { + // if it is behind a reverse proxy, use "https" as default scheme in case the site admin forgets to set the correct forwarded-protocol headers + return guessRequestScheme(req, "https") + "://" + host + setting.AppSubURL + "/" + } else if req.Host != "" { + // if it is not behind a reverse proxy, use the scheme from config options, meanwhile use "https" as much as possible + defaultScheme := util.Iif(setting.Protocol == "http", "http", "https") + return guessRequestScheme(req, defaultScheme) + "://" + req.Host + setting.AppSubURL + "/" } return setting.AppURL } diff --git a/modules/httplib/url_test.go b/modules/httplib/url_test.go index 0eab1bee90..e021cd610d 100644 --- a/modules/httplib/url_test.go +++ b/modules/httplib/url_test.go @@ -40,6 +40,7 @@ func TestIsRelativeURL(t *testing.T) { } func TestMakeAbsoluteURL(t *testing.T) { + defer test.MockVariableValue(&setting.Protocol, "http")() defer test.MockVariableValue(&setting.AppURL, "http://the-host/sub/")() defer test.MockVariableValue(&setting.AppSubURL, "/sub")() @@ -60,7 +61,7 @@ func TestMakeAbsoluteURL(t *testing.T) { "X-Forwarded-Host": {"forwarded-host"}, }, }) - assert.Equal(t, "http://forwarded-host/sub/foo", MakeAbsoluteURL(ctx, "/foo")) + assert.Equal(t, "https://forwarded-host/sub/foo", MakeAbsoluteURL(ctx, "/foo")) ctx = context.WithValue(ctx, RequestContextKey, &http.Request{ Host: "user-host",