Skip to content

Commit f5a8acd

Browse files
committed
Allow LocalURL to be passed in the Host header
Fix go-gitea#32554
1 parent 5eb0ee4 commit f5a8acd

File tree

2 files changed

+38
-1
lines changed

2 files changed

+38
-1
lines changed

modules/httplib/url.go

+10-1
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,21 @@ func GuessCurrentHostURL(ctx context.Context) string {
6868
// There are some cases:
6969
// 1. The reverse proxy is configured correctly, it passes "X-Forwarded-Proto/Host" headers. Perfect, Gitea can handle it correctly.
7070
// 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.
71-
// 3. There is no reverse proxy.
71+
// 3. There is no reverse proxy. In this case, we allow the configured LocalURL to be passed in the Host header.
7272
// Without an extra config option, Gitea is impossible to distinguish between case 2 and case 3,
7373
// then case 2 would result in wrong guess like guessed AppURL becomes "http://gitea:3000/", which is not accessible by end users.
7474
// So in the future maybe it should introduce a new config option, to let site admin decide how to guess the AppURL.
7575
reqScheme := getRequestScheme(req)
7676
if reqScheme == "" {
77+
if setting.LocalURL != "" {
78+
localURL, err := url.Parse(setting.LocalURL)
79+
if err == nil &&
80+
strings.EqualFold(req.Host, localURL.Host) &&
81+
(req.TLS != nil) == (localURL.Scheme == "https") {
82+
return strings.TrimSuffix(setting.LocalURL, setting.AppSubURL+"/")
83+
}
84+
}
85+
7786
return strings.TrimSuffix(setting.AppURL, setting.AppSubURL+"/")
7887
}
7988
// X-Forwarded-Host has many problems: non-standard, not well-defined (X-Forwarded-Port or not), conflicts with Host header.

modules/httplib/url_test.go

+28
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package httplib
55

66
import (
77
"context"
8+
"crypto/tls"
89
"net/http"
910
"testing"
1011

@@ -39,6 +40,33 @@ func TestIsRelativeURL(t *testing.T) {
3940
}
4041
}
4142

43+
func TestGuessCurrentHostURL(t *testing.T) {
44+
defer test.MockVariableValue(&setting.AppURL, "http://cfg-host/sub/")()
45+
defer test.MockVariableValue(&setting.LocalURL, "http://localhost:3000/sub/")()
46+
defer test.MockVariableValue(&setting.AppSubURL, "/sub")()
47+
48+
ctx := context.Background()
49+
assert.Equal(t, "http://cfg-host", GuessCurrentHostURL(ctx))
50+
51+
ctx = context.WithValue(ctx, RequestContextKey, &http.Request{
52+
Host: "localhost:3000",
53+
})
54+
assert.Equal(t, "http://localhost:3000", GuessCurrentHostURL(ctx))
55+
56+
ctx = context.WithValue(ctx, RequestContextKey, &http.Request{
57+
Host: "localhost:3000",
58+
TLS: &tls.ConnectionState{},
59+
})
60+
assert.Equal(t, "http://cfg-host", GuessCurrentHostURL(ctx))
61+
62+
defer test.MockVariableValue(&setting.LocalURL, "https://localhost/sub/")()
63+
ctx = context.WithValue(ctx, RequestContextKey, &http.Request{
64+
Host: "localhost",
65+
TLS: &tls.ConnectionState{},
66+
})
67+
assert.Equal(t, "https://localhost", GuessCurrentHostURL(ctx))
68+
}
69+
4270
func TestMakeAbsoluteURL(t *testing.T) {
4371
defer test.MockVariableValue(&setting.Protocol, "http")()
4472
defer test.MockVariableValue(&setting.AppURL, "http://cfg-host/sub/")()

0 commit comments

Comments
 (0)