1
1
mirror of https://github.com/go-gitea/gitea synced 2025-07-22 18:28:37 +00:00

Make ROOT_URL support using request Host header (#32564)

Resolve #32554

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
Jannis Pohl
2025-04-20 13:43:48 +02:00
committed by GitHub
parent af6be75adb
commit d1a3bd6814
5 changed files with 80 additions and 32 deletions

View File

@@ -70,11 +70,16 @@ func GuessCurrentHostURL(ctx context.Context) string {
// 1. The reverse proxy is configured correctly, it passes "X-Forwarded-Proto/Host" headers. Perfect, Gitea can handle it correctly.
// 2. The reverse proxy is not configured correctly, doesn't pass "X-Forwarded-Proto/Host" headers, eg: only one "proxy_pass http://gitea:3000" in Nginx.
// 3. There is no reverse proxy.
// Without an extra config option, Gitea is impossible to distinguish between case 2 and case 3,
// then case 2 would result in wrong guess like guessed AppURL becomes "http://gitea:3000/", which is not accessible by end users.
// So in the future maybe it should introduce a new config option, to let site admin decide how to guess the AppURL.
// Without more information, Gitea is impossible to distinguish between case 2 and case 3, then case 2 would result in
// wrong guess like guessed AppURL becomes "http://gitea:3000/" behind a "https" reverse proxy, which is not accessible by end users.
// So we introduced "UseHostHeader" option, it could be enabled by setting "ROOT_URL" to empty
reqScheme := getRequestScheme(req)
if reqScheme == "" {
// if no reverse proxy header, try to use "Host" header for absolute URL
if setting.UseHostHeader && req.Host != "" {
return util.Iif(req.TLS == nil, "http://", "https://") + req.Host
}
// fall back to default AppURL
return strings.TrimSuffix(setting.AppURL, setting.AppSubURL+"/")
}
// X-Forwarded-Host has many problems: non-standard, not well-defined (X-Forwarded-Port or not), conflicts with Host header.

View File

@@ -5,6 +5,7 @@ package httplib
import (
"context"
"crypto/tls"
"net/http"
"testing"
@@ -39,6 +40,25 @@ func TestIsRelativeURL(t *testing.T) {
}
}
func TestGuessCurrentHostURL(t *testing.T) {
defer test.MockVariableValue(&setting.AppURL, "http://cfg-host/sub/")()
defer test.MockVariableValue(&setting.AppSubURL, "/sub")()
defer test.MockVariableValue(&setting.UseHostHeader, false)()
ctx := t.Context()
assert.Equal(t, "http://cfg-host", GuessCurrentHostURL(ctx))
ctx = context.WithValue(ctx, RequestContextKey, &http.Request{Host: "localhost:3000"})
assert.Equal(t, "http://cfg-host", GuessCurrentHostURL(ctx))
defer test.MockVariableValue(&setting.UseHostHeader, true)()
ctx = context.WithValue(ctx, RequestContextKey, &http.Request{Host: "http-host:3000"})
assert.Equal(t, "http://http-host:3000", GuessCurrentHostURL(ctx))
ctx = context.WithValue(ctx, RequestContextKey, &http.Request{Host: "http-host", TLS: &tls.ConnectionState{}})
assert.Equal(t, "https://http-host", GuessCurrentHostURL(ctx))
}
func TestMakeAbsoluteURL(t *testing.T) {
defer test.MockVariableValue(&setting.Protocol, "http")()
defer test.MockVariableValue(&setting.AppURL, "http://cfg-host/sub/")()