package api import ( "net/http" "net/url" "strings" ) func (api *Api) GetAbsoluteUrl(r *http.Request, uri string) *url.URL { callbackURL := fullURL(r) callbackURL.RawQuery = "" callbackURL.Fragment = "" if uri == "/" && api.cfg.UrlBasePath != "/" { uri = api.cfg.UrlBasePath } if parsed, err := url.Parse(uri); err == nil { callbackURL.Path = parsed.Path callbackURL.RawQuery = parsed.RawQuery } else { callbackURL.Path = uri } return callbackURL } func fullURL(r *http.Request) *url.URL { u := *r.URL u.Scheme = "http" u.Host = r.Host // RFC 7239 Forwarded header if fwd := r.Header.Get("Forwarded"); fwd != "" { parts := strings.SplitSeq(fwd, ";") for p := range parts { p = strings.TrimSpace(p) if after, ok := strings.CutPrefix(p, "proto="); ok { u.Scheme = after } else if after, ok := strings.CutPrefix(p, "host="); ok { u.Host = after } } } if proto := r.Header.Get("X-Forwarded-Proto"); proto != "" { u.Scheme = strings.Split(proto, ",")[0] } if h := r.Header.Get("X-Forwarded-Host"); h != "" { u.Host = strings.Split(h, ",")[0] } if port := r.Header.Get("X-Forwarded-Port"); port != "" && port != "443" && port != "80" && !strings.Contains(u.Host, ":") { u.Host = u.Host + ":" + port } if r.TLS != nil { u.Scheme = "https" } return &u }