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

Fix duplicate sub-path for avatars (#31365)

Fix #31361, and add tests

And this PR introduces an undocumented & debug-purpose-only config
option: `USE_SUB_URL_PATH`. It does nothing for end users, it only helps
the development of sub-path related problems.

And also fix #31366

Co-authored-by: @ExplodingDragon
This commit is contained in:
wxiaoguang
2024-06-15 11:43:57 +08:00
committed by GitHub
parent 23147494a7
commit 84cbb6c4d2
13 changed files with 150 additions and 40 deletions

View File

@@ -57,11 +57,16 @@ func getForwardedHost(req *http.Request) string {
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
// GuessCurrentAppURL tries to guess the current full app URL (with sub-path) by http headers. It always has a '/' suffix, exactly the same as setting.AppURL
func GuessCurrentAppURL(ctx context.Context) string {
return GuessCurrentHostURL(ctx) + setting.AppSubURL + "/"
}
// 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 {
req, ok := ctx.Value(RequestContextKey).(*http.Request)
if !ok {
return setting.AppURL
return strings.TrimSuffix(setting.AppURL, setting.AppSubURL+"/")
}
// If no scheme provided by reverse proxy, then do not guess the AppURL, use the configured one.
// At the moment, if site admin doesn't configure the proxy headers correctly, then Gitea would guess wrong.
@@ -74,20 +79,27 @@ func GuessCurrentAppURL(ctx context.Context) string {
// So in the future maybe it should introduce a new config option, to let site admin decide how to guess the AppURL.
reqScheme := getRequestScheme(req)
if reqScheme == "" {
return setting.AppURL
return strings.TrimSuffix(setting.AppURL, setting.AppSubURL+"/")
}
reqHost := getForwardedHost(req)
if reqHost == "" {
reqHost = req.Host
}
return reqScheme + "://" + reqHost + setting.AppSubURL + "/"
return reqScheme + "://" + reqHost
}
func MakeAbsoluteURL(ctx context.Context, s string) string {
if IsRelativeURL(s) {
return GuessCurrentAppURL(ctx) + strings.TrimPrefix(s, "/")
// MakeAbsoluteURL tries to make a link to an absolute URL:
// * If link is empty, it returns the current app URL.
// * If link is absolute, it returns the link.
// * Otherwise, it returns the current host URL + link, the link itself should have correct sub-path (AppSubURL) if needed.
func MakeAbsoluteURL(ctx context.Context, link string) string {
if link == "" {
return GuessCurrentAppURL(ctx)
}
return s
if !IsRelativeURL(link) {
return link
}
return GuessCurrentHostURL(ctx) + "/" + strings.TrimPrefix(link, "/")
}
func IsCurrentGiteaSiteURL(ctx context.Context, s string) bool {

View File

@@ -46,14 +46,14 @@ func TestMakeAbsoluteURL(t *testing.T) {
ctx := context.Background()
assert.Equal(t, "http://cfg-host/sub/", MakeAbsoluteURL(ctx, ""))
assert.Equal(t, "http://cfg-host/sub/foo", MakeAbsoluteURL(ctx, "foo"))
assert.Equal(t, "http://cfg-host/sub/foo", MakeAbsoluteURL(ctx, "/foo"))
assert.Equal(t, "http://cfg-host/foo", MakeAbsoluteURL(ctx, "foo"))
assert.Equal(t, "http://cfg-host/foo", MakeAbsoluteURL(ctx, "/foo"))
assert.Equal(t, "http://other/foo", MakeAbsoluteURL(ctx, "http://other/foo"))
ctx = context.WithValue(ctx, RequestContextKey, &http.Request{
Host: "user-host",
})
assert.Equal(t, "http://cfg-host/sub/foo", MakeAbsoluteURL(ctx, "/foo"))
assert.Equal(t, "http://cfg-host/foo", MakeAbsoluteURL(ctx, "/foo"))
ctx = context.WithValue(ctx, RequestContextKey, &http.Request{
Host: "user-host",
@@ -61,7 +61,7 @@ func TestMakeAbsoluteURL(t *testing.T) {
"X-Forwarded-Host": {"forwarded-host"},
},
})
assert.Equal(t, "http://cfg-host/sub/foo", MakeAbsoluteURL(ctx, "/foo"))
assert.Equal(t, "http://cfg-host/foo", MakeAbsoluteURL(ctx, "/foo"))
ctx = context.WithValue(ctx, RequestContextKey, &http.Request{
Host: "user-host",
@@ -70,7 +70,7 @@ func TestMakeAbsoluteURL(t *testing.T) {
"X-Forwarded-Proto": {"https"},
},
})
assert.Equal(t, "https://forwarded-host/sub/foo", MakeAbsoluteURL(ctx, "/foo"))
assert.Equal(t, "https://forwarded-host/foo", MakeAbsoluteURL(ctx, "/foo"))
}
func TestIsCurrentGiteaSiteURL(t *testing.T) {

18
modules/setting/global.go Normal file
View File

@@ -0,0 +1,18 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package setting
// Global settings
var (
// RunUser is the OS user that Gitea is running as. ini:"RUN_USER"
RunUser string
// RunMode is the running mode of Gitea, it only accepts two values: "dev" and "prod".
// Non-dev values will be replaced by "prod". ini: "RUN_MODE"
RunMode string
// IsProd is true if RunMode is not "dev"
IsProd bool
// AppName is the Application name, used in the page title. ini: "APP_NAME"
AppName string
)

View File

@@ -40,16 +40,16 @@ const (
LandingPageLogin LandingPage = "/user/login"
)
// Server settings
var (
// AppName is the Application name, used in the page title.
// It maps to ini:"APP_NAME"
AppName string
// AppURL is the Application ROOT_URL. It always has a '/' suffix
// It maps to ini:"ROOT_URL"
AppURL string
// AppSubURL represents the sub-url mounting point for gitea. It is either "" or starts with '/' and ends without '/', such as '/{subpath}'.
// This value is empty if site does not have sub-url.
AppSubURL string
// 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.
UseSubURLPath bool
// AppDataPath is the default path for storing data.
// It maps to ini:"APP_DATA_PATH" in [server] and defaults to AppWorkPath + "/data"
AppDataPath string
@@ -59,8 +59,6 @@ var (
// AssetVersion holds a opaque value that is used for cache-busting assets
AssetVersion string
// Server settings
Protocol Scheme
UseProxyProtocol bool // `ini:"USE_PROXY_PROTOCOL"`
ProxyProtocolTLSBridging bool //`ini:"PROXY_PROTOCOL_TLS_BRIDGING"`
@@ -275,9 +273,10 @@ func loadServerFrom(rootCfg ConfigProvider) {
// This should be TrimRight to ensure that there is only a single '/' at the end of AppURL.
AppURL = strings.TrimRight(appURL.String(), "/") + "/"
// Suburl should start with '/' and end without '/', such as '/{subpath}'.
// AppSubURL should start with '/' and end without '/', such as '/{subpath}'.
// This value is empty if site does not have sub-url.
AppSubURL = strings.TrimSuffix(appURL.Path, "/")
UseSubURLPath = sec.Key("USE_SUB_URL_PATH").MustBool(false)
StaticURLPrefix = strings.TrimSuffix(sec.Key("STATIC_URL_PREFIX").MustString(AppSubURL), "/")
// Check if Domain differs from AppURL domain than update it to AppURL's domain

View File

@@ -25,12 +25,7 @@ var (
// AppStartTime store time gitea has started
AppStartTime time.Time
// Other global setting objects
CfgProvider ConfigProvider
RunMode string
RunUser string
IsProd bool
IsWindows bool
// IsInTesting indicates whether the testing is running. A lot of unreliable code causes a lot of nonsense error logs during testing