Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions custom/conf/app.example.ini
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ RUN_USER = ; git
;; especially when the Gitea instance needs to be accessed in a container network.
;; * legacy: detect the public URL from "Host" header if "X-Forwarded-Proto" header exists, otherwise use "ROOT_URL".
;; * auto: always use "Host" header, and also use "X-Forwarded-Proto" header if it exists. If no "Host" header, use "ROOT_URL".
;; * never: always use "ROOT_URL", never detect from request headers.
;PUBLIC_URL_DETECTION = legacy
;;
;; For development purpose only. It makes Gitea handle sub-path ("/sub-path/owner/repo/...") directly when debugging without a reverse proxy.
Expand Down
4 changes: 4 additions & 0 deletions modules/httplib/url.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ func GuessCurrentAppURL(ctx context.Context) string {

// GuessCurrentHostURL tries to guess the current full host URL (no sub-path) by http headers, there is no trailing slash.
func GuessCurrentHostURL(ctx context.Context) string {
// "never" means always trust ROOT_URL and skip any request header detection.
if setting.PublicURLDetection == setting.PublicURLNever {
return strings.TrimSuffix(setting.AppURL, setting.AppSubURL+"/")
}
// Try the best guess to get the current host URL (will be used for public URL) by http headers.
// At the moment, if site admin doesn't configure the proxy headers correctly, then Gitea would guess wrong.
// There are some cases:
Expand Down
15 changes: 15 additions & 0 deletions modules/httplib/url_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,21 @@ func TestGuessCurrentHostURL(t *testing.T) {
ctx = context.WithValue(t.Context(), RequestContextKey, &http.Request{Host: "req-host:3000", Header: headersWithProto})
assert.Equal(t, "https://req-host:3000", GuessCurrentHostURL(ctx))
})

t.Run("Never", func(t *testing.T) {
defer test.MockVariableValue(&setting.PublicURLDetection, setting.PublicURLNever)()

assert.Equal(t, "http://cfg-host", GuessCurrentHostURL(t.Context()))

ctx := context.WithValue(t.Context(), RequestContextKey, &http.Request{Host: "req-host:3000"})
assert.Equal(t, "http://cfg-host", GuessCurrentHostURL(ctx))

ctx = context.WithValue(t.Context(), RequestContextKey, &http.Request{Host: "req-host:3000", TLS: &tls.ConnectionState{}})
assert.Equal(t, "http://cfg-host", GuessCurrentHostURL(ctx))

ctx = context.WithValue(t.Context(), RequestContextKey, &http.Request{Host: "req-host:3000", Header: headersWithProto})
assert.Equal(t, "http://cfg-host", GuessCurrentHostURL(ctx))
})
}

func TestMakeAbsoluteURL(t *testing.T) {
Expand Down
3 changes: 2 additions & 1 deletion modules/setting/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const (
const (
PublicURLAuto = "auto"
PublicURLLegacy = "legacy"
PublicURLNever = "never"
)

// Server settings
Expand Down Expand Up @@ -286,7 +287,7 @@ func loadServerFrom(rootCfg ConfigProvider) {
defaultAppURL := string(Protocol) + "://" + Domain + ":" + HTTPPort
AppURL = sec.Key("ROOT_URL").MustString(defaultAppURL)
PublicURLDetection = sec.Key("PUBLIC_URL_DETECTION").MustString(PublicURLLegacy)
if PublicURLDetection != PublicURLAuto && PublicURLDetection != PublicURLLegacy {
if PublicURLDetection != PublicURLAuto && PublicURLDetection != PublicURLLegacy && PublicURLDetection != PublicURLNever {
log.Fatal("Invalid PUBLIC_URL_DETECTION value: %s", PublicURLDetection)
}

Expand Down