Skip to content

Commit c3b1578

Browse files
committed
refactor
1 parent 55b1e68 commit c3b1578

File tree

4 files changed

+59
-45
lines changed

4 files changed

+59
-45
lines changed

custom/conf/app.example.ini

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -59,27 +59,15 @@ RUN_USER = ; git
5959
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6060
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6161
;;
62-
;; The protocol the server listens on. One of 'http', 'https', 'http+unix', 'fcgi' or 'fcgi+unix'. Defaults to 'http'
63-
;; Note: Value must be lowercase.
62+
;; The protocol the server listens on. One of "http", "https", "http+unix", "fcgi" or "fcgi+unix".
6463
;PROTOCOL = http
6564
;;
66-
;; Expect PROXY protocol headers on connections
67-
;USE_PROXY_PROTOCOL = false
68-
;;
69-
;; Use PROXY protocol in TLS Bridging mode
70-
;PROXY_PROTOCOL_TLS_BRIDGING = false
71-
;;
72-
; Timeout to wait for PROXY protocol header (set to 0 to have no timeout)
73-
;PROXY_PROTOCOL_HEADER_TIMEOUT=5s
74-
;;
75-
; Accept PROXY protocol headers with UNKNOWN type
76-
;PROXY_PROTOCOL_ACCEPT_UNKNOWN=false
77-
;;
78-
;; Set the domain for the server
65+
;; Set the domain for the server.
66+
;; Most users should set it to the real website domain of their Gitea instance.
7967
;DOMAIN = localhost
8068
;;
8169
;; The AppURL used by Gitea to generate absolute links, defaults to "{PROTOCOL}://{DOMAIN}:{HTTP_PORT}/".
82-
;; Most users should set it to the real website URL of their Gitea instance.
70+
;; When it is empty, Gitea will use HTTP "Host" header to generate ROOT_URL, and fall back to the default one if no "Host" header.
8371
;ROOT_URL =
8472
;;
8573
;; For development purpose only. It makes Gitea handle sub-path ("/sub-path/owner/repo/...") directly when debugging without a reverse proxy.
@@ -90,13 +78,25 @@ RUN_USER = ; git
9078
;STATIC_URL_PREFIX =
9179
;;
9280
;; The address to listen on. Either a IPv4/IPv6 address or the path to a unix socket.
93-
;; If PROTOCOL is set to `http+unix` or `fcgi+unix`, this should be the name of the Unix socket file to use.
81+
;; If PROTOCOL is set to "http+unix" or "fcgi+unix", this should be the name of the Unix socket file to use.
9482
;; Relative paths will be made absolute against the _`AppWorkPath`_.
9583
;HTTP_ADDR = 0.0.0.0
9684
;;
97-
;; The port to listen on. Leave empty when using a unix socket.
85+
;; The port to listen on for "http" or "https" protocol. Leave empty when using a unix socket.
9886
;HTTP_PORT = 3000
9987
;;
88+
;; Expect PROXY protocol headers on connections
89+
;USE_PROXY_PROTOCOL = false
90+
;;
91+
;; Use PROXY protocol in TLS Bridging mode
92+
;PROXY_PROTOCOL_TLS_BRIDGING = false
93+
;;
94+
; Timeout to wait for PROXY protocol header (set to 0 to have no timeout)
95+
;PROXY_PROTOCOL_HEADER_TIMEOUT=5s
96+
;;
97+
; Accept PROXY protocol headers with UNKNOWN type
98+
;PROXY_PROTOCOL_ACCEPT_UNKNOWN=false
99+
;;
100100
;; If REDIRECT_OTHER_PORT is true, and PROTOCOL is set to https an http server
101101
;; will be started on PORT_TO_REDIRECT and it will redirect plain, non-secure http requests to the main
102102
;; ROOT_URL. Defaults are false for REDIRECT_OTHER_PORT and 80 for

modules/httplib/url.go

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,18 +70,16 @@ func GuessCurrentHostURL(ctx context.Context) string {
7070
// 1. The reverse proxy is configured correctly, it passes "X-Forwarded-Proto/Host" headers. Perfect, Gitea can handle it correctly.
7171
// 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.
7272
// 3. There is no reverse proxy.
73-
// With the "USE_HOST_HEADER" config option disabled (default), Gitea is impossible to distinguish between case 2 and case 3,
74-
// When enabling "USE_HOST_HEADER", any reverse proxies must be configured to properly pass "X-Forwarded-Proto/Host" headers,
75-
// otherwise this would result in wrong guess like guessed AppURL becomes "http://gitea:3000/", which is not accessible by end users.
73+
// Without more information, Gitea is impossible to distinguish between case 2 and case 3, then case 2 would result in
74+
// wrong guess like guessed AppURL becomes "http://gitea:3000/" behind a "https" reverse proxy, which is not accessible by end users.
75+
// So we introduced "UseHostHeader" option, it could be enabled by setting "ROOT_URL" to empty
7676
reqScheme := getRequestScheme(req)
7777
if reqScheme == "" {
78+
// if no reverse proxy header, try to use "Host" header for absolute URL
7879
if setting.UseHostHeader && req.Host != "" {
79-
if req.TLS != nil {
80-
return "https://" + req.Host
81-
}
82-
return "http://" + req.Host
80+
return util.Iif(req.TLS == nil, "http://", "https://") + req.Host
8381
}
84-
82+
// fall back to default AppURL
8583
return strings.TrimSuffix(setting.AppURL, setting.AppSubURL+"/")
8684
}
8785
// 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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,15 @@ func TestGuessCurrentHostURL(t *testing.T) {
5555
defer test.MockVariableValue(&setting.UseHostHeader, true)()
5656

5757
ctx = context.WithValue(ctx, RequestContextKey, &http.Request{
58-
Host: "localhost:3000",
58+
Host: "http-host:3000",
5959
})
60-
assert.Equal(t, "http://localhost:3000", GuessCurrentHostURL(ctx))
60+
assert.Equal(t, "http://http-host:3000", GuessCurrentHostURL(ctx))
6161

6262
ctx = context.WithValue(ctx, RequestContextKey, &http.Request{
63-
Host: "localhost",
63+
Host: "http-host",
6464
TLS: &tls.ConnectionState{},
6565
})
66-
assert.Equal(t, "https://localhost", GuessCurrentHostURL(ctx))
66+
assert.Equal(t, "https://http-host", GuessCurrentHostURL(ctx))
6767
}
6868

6969
func TestMakeAbsoluteURL(t *testing.T) {

modules/setting/server.go

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -46,29 +46,37 @@ var (
4646
// AppURL is the Application ROOT_URL. It always has a '/' suffix
4747
// It maps to ini:"ROOT_URL"
4848
AppURL string
49-
// AppSubURL represents the sub-url mounting point for gitea. It is either "" or starts with '/' and ends without '/', such as '/{subpath}'.
49+
50+
// AppSubURL represents the sub-url mounting point for gitea, parsed from "ROOT_URL"
51+
// It is either "" or starts with '/' and ends without '/', such as '/{sub-path}'.
5052
// This value is empty if site does not have sub-url.
5153
AppSubURL string
52-
// UseSubURLPath makes Gitea handle requests with sub-path like "/sub-path/owner/repo/...", to make it easier to debug sub-path related problems without a reverse proxy.
54+
55+
// UseSubURLPath makes Gitea handle requests with sub-path like "/sub-path/owner/repo/...",
56+
// to make it easier to debug sub-path related problems without a reverse proxy.
5357
UseSubURLPath bool
54-
// UseHostHeader makes Gitea always use the "Host" request header for construction of absolute URLs.
55-
// This requires any reverse proxy to properly pass headers like "X-Forwarded-Proto" and "Host".
56-
// It maps to ini:"USE_HOST_HEADER" in [server] and defaults to false
58+
59+
// UseHostHeader makes Gitea prefer to use the "Host" request header for construction of absolute URLs.
5760
UseHostHeader bool
61+
5862
// AppDataPath is the default path for storing data.
5963
// It maps to ini:"APP_DATA_PATH" in [server] and defaults to AppWorkPath + "/data"
6064
AppDataPath string
65+
6166
// LocalURL is the url for locally running applications to contact Gitea. It always has a '/' suffix
6267
// It maps to ini:"LOCAL_ROOT_URL" in [server]
6368
LocalURL string
64-
// AssetVersion holds a opaque value that is used for cache-busting assets
69+
70+
// AssetVersion holds an opaque value that is used for cache-busting assets
6571
AssetVersion string
6672

67-
appTempPathInternal string // the temporary path for the app, it is only an internal variable, do not use it, always use AppDataTempDir
73+
// appTempPathInternal is the temporary path for the app, it is only an internal variable
74+
// DO NOT use it directly, always use AppDataTempDir
75+
appTempPathInternal string
6876

6977
Protocol Scheme
70-
UseProxyProtocol bool // `ini:"USE_PROXY_PROTOCOL"`
71-
ProxyProtocolTLSBridging bool //`ini:"PROXY_PROTOCOL_TLS_BRIDGING"`
78+
UseProxyProtocol bool
79+
ProxyProtocolTLSBridging bool
7280
ProxyProtocolHeaderTimeout time.Duration
7381
ProxyProtocolAcceptUnknown bool
7482
Domain string
@@ -185,13 +193,14 @@ func loadServerFrom(rootCfg ConfigProvider) {
185193
EnableAcme = sec.Key("ENABLE_LETSENCRYPT").MustBool(false)
186194
}
187195

188-
Protocol = HTTP
189196
protocolCfg := sec.Key("PROTOCOL").String()
190197
if protocolCfg != "https" && EnableAcme {
191198
log.Fatal("ACME could only be used with HTTPS protocol")
192199
}
193200

194201
switch protocolCfg {
202+
case "http":
203+
Protocol = HTTP
195204
case "https":
196205
Protocol = HTTPS
197206
if EnableAcme {
@@ -247,7 +256,7 @@ func loadServerFrom(rootCfg ConfigProvider) {
247256
case "unix":
248257
log.Warn("unix PROTOCOL value is deprecated, please use http+unix")
249258
fallthrough
250-
case "http+unix":
259+
default: // "http+unix"
251260
Protocol = HTTPUnix
252261
}
253262
UnixSocketPermissionRaw := sec.Key("UNIX_SOCKET_PERMISSION").MustString("666")
@@ -260,6 +269,8 @@ func loadServerFrom(rootCfg ConfigProvider) {
260269
if !filepath.IsAbs(HTTPAddr) {
261270
HTTPAddr = filepath.Join(AppWorkPath, HTTPAddr)
262271
}
272+
default:
273+
log.Fatal("Invalid PROTOCOL %q", Protocol)
263274
}
264275
UseProxyProtocol = sec.Key("USE_PROXY_PROTOCOL").MustBool(false)
265276
ProxyProtocolTLSBridging = sec.Key("PROXY_PROTOCOL_TLS_BRIDGING").MustBool(false)
@@ -272,12 +283,16 @@ func loadServerFrom(rootCfg ConfigProvider) {
272283
PerWritePerKbTimeout = sec.Key("PER_WRITE_PER_KB_TIMEOUT").MustDuration(PerWritePerKbTimeout)
273284

274285
defaultAppURL := string(Protocol) + "://" + Domain + ":" + HTTPPort
275-
AppURL = sec.Key("ROOT_URL").MustString(defaultAppURL)
286+
AppURL = sec.Key("ROOT_URL").String()
287+
if AppURL == "" {
288+
UseHostHeader = true
289+
AppURL = defaultAppURL
290+
}
276291

277292
// Check validity of AppURL
278293
appURL, err := url.Parse(AppURL)
279294
if err != nil {
280-
log.Fatal("Invalid ROOT_URL '%s': %s", AppURL, err)
295+
log.Fatal("Invalid ROOT_URL %q: %s", AppURL, err)
281296
}
282297
// Remove default ports from AppURL.
283298
// (scheme-based URL normalization, RFC 3986 section 6.2.3)
@@ -291,7 +306,6 @@ func loadServerFrom(rootCfg ConfigProvider) {
291306
// This value is empty if site does not have sub-url.
292307
AppSubURL = strings.TrimSuffix(appURL.Path, "/")
293308
UseSubURLPath = sec.Key("USE_SUB_URL_PATH").MustBool(false)
294-
UseHostHeader = sec.Key("USE_HOST_HEADER").MustBool(false)
295309
StaticURLPrefix = strings.TrimSuffix(sec.Key("STATIC_URL_PREFIX").MustString(AppSubURL), "/")
296310

297311
// Check if Domain differs from AppURL domain than update it to AppURL's domain
@@ -314,13 +328,15 @@ func loadServerFrom(rootCfg ConfigProvider) {
314328
defaultLocalURL = AppURL
315329
case FCGIUnix:
316330
defaultLocalURL = AppURL
317-
default:
331+
case HTTP, HTTPS:
318332
defaultLocalURL = string(Protocol) + "://"
319333
if HTTPAddr == "0.0.0.0" {
320334
defaultLocalURL += net.JoinHostPort("localhost", HTTPPort) + "/"
321335
} else {
322336
defaultLocalURL += net.JoinHostPort(HTTPAddr, HTTPPort) + "/"
323337
}
338+
default:
339+
log.Fatal("Invalid PROTOCOL %q", Protocol)
324340
}
325341
LocalURL = sec.Key("LOCAL_ROOT_URL").MustString(defaultLocalURL)
326342
LocalURL = strings.TrimRight(LocalURL, "/") + "/"

0 commit comments

Comments
 (0)