/
githubmirror
/
photoprism
Обзор
Документация
Войти
/
githubmirror
/
photoprism
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
develop
pkg/http/scheme/url.go
130 строк
4 KB
Michael Mayer
Cluster: Compact code comments in the OIDC follow-up changes
09 июн 2026, 13:20
09 июн 2026, 13:20
b88429f
Код
Авторство
О чём код?
package scheme import ( "net/url" "strings" "sync" ) // NormalizeBaseURLMaxLen caps the input length eligible for caching; longer // strings still normalize correctly but bypass the cache so a single oversized // input cannot bloat the cache map. const NormalizeBaseURLMaxLen = 2048 // NormalizeBaseURLCacheEntries bounds the in-memory cache. In practice only a // handful of distinct base URLs (SiteUrl, CdnUrl, possibly an empty string) // are normalized over the process lifetime; the cap is a safety net so a // runaway caller cannot grow the map without limit. const NormalizeBaseURLCacheEntries = 128 var ( normalizeBaseURLCache = make(map[string]string, NormalizeBaseURLCacheEntries) normalizeBaseURLCacheMu sync.RWMutex ) // NormalizeBaseURL returns a base URL with a trailing slash if s is not empty // or does not contain only whitespace. The default port, query strings, // and fragments are omitted, but Userinfo is preserved. // If parsing fails, NormalizeBaseURL returns s with a trailing slash appended. // // Results are cached by raw input string. The output is a pure function of the // input, so cache entries never need to be invalidated; the only bounds are // the input length cap and the maximum number of cached entries. func NormalizeBaseURL(s string) string { if len(s) > NormalizeBaseURLMaxLen { return normalizeBaseURL(s) } normalizeBaseURLCacheMu.RLock() if out, ok := normalizeBaseURLCache[s]; ok { normalizeBaseURLCacheMu.RUnlock() return out } normalizeBaseURLCacheMu.RUnlock() out := normalizeBaseURL(s) normalizeBaseURLCacheMu.Lock() if len(normalizeBaseURLCache) < NormalizeBaseURLCacheEntries { normalizeBaseURLCache[s] = out } normalizeBaseURLCacheMu.Unlock() return out } // normalizeBaseURL implements the uncached normalization used by NormalizeBaseURL. func normalizeBaseURL(s string) string { s = strings.TrimSpace(s) if s == "" { return "" } u, err := url.Parse(s) if err != nil { return strings.TrimRight(s, "/") + "/" } StripDefaultPort(u) u.RawQuery = "" u.ForceQuery = false u.Fragment = "" u.RawFragment = "" u.Path = strings.TrimRight(u.Path, "/") + "/" return u.String() } // OriginURL returns the scheme://host/ origin of s (trailing slash; no path, // query, fragment, or userinfo). A non-default port is preserved; the scheme's // default port is stripped so the result matches a NormalizeBaseURL'd issuer. // Returns "" when s is empty or has no scheme/host. func OriginURL(s string) string { u, err := url.Parse(strings.TrimSpace(s)) if err != nil || u.Scheme == "" || u.Host == "" { return "" } StripDefaultPort(u) return u.Scheme + "://" + u.Host + "/" } // ResolveAdvertiseURL returns the normalized base URL the Portal should // use to reach a PhotoPrism instance, using siteURL's path as the source // of truth. The result always carries a trailing slash so callers can // concatenate an API path directly (e.g. `result + "api/v1/users/" + uid`). func ResolveAdvertiseURL(advertiseURL, siteURL string) string { advertiseURL = NormalizeBaseURL(advertiseURL) siteURL = NormalizeBaseURL(siteURL) if advertiseURL == "" && siteURL == "" { return "" } if advertiseURL == "" || advertiseURL == siteURL { return siteURL } // If paths diverge, use the SiteURL's path as the authoritative source. var sitePath string if siteURL != "" { if s, err := url.Parse(siteURL); err == nil { sitePath = strings.TrimRight(s.Path, "/") } } a, err := url.Parse(advertiseURL) if err != nil || a.Host == "" { return advertiseURL } if sitePath != "" { a.Path = sitePath + "/" a.RawPath = "" } return a.String() }