Files
telemt-api/internal/proxy/reverse.go
T

69 lines
1.7 KiB
Go

package proxy
import (
"net/http"
"net/http/httputil"
"net/url"
"path"
"strings"
)
// NewReverseProxy builds a reverse proxy to target base URL with path rewriting:
// stripPrefix (/api/{alias}) + pathPrefix (/v1) + remainder, prepended to target.Path
// (so base_url https://host/api/ yields upstream /api/v1/...).
func NewReverseProxy(target *url.URL, stripPrefix, pathPrefix string, setAuth string) *httputil.ReverseProxy {
proxy := httputil.NewSingleHostReverseProxy(target)
orig := proxy.Director
targetQuery := target.RawQuery
proxy.Director = func(req *http.Request) {
p := req.URL.Path
if !strings.HasPrefix(p, stripPrefix) {
orig(req)
if setAuth != "" {
req.Header.Set("Authorization", setAuth)
}
return
}
rest := strings.TrimPrefix(p, stripPrefix)
rest = strings.TrimPrefix(rest, "/")
upPath := buildUpstreamPath(target.Path, pathPrefix, rest)
req.URL.Scheme = target.Scheme
req.URL.Host = target.Host
req.URL.Path = upPath
req.URL.RawPath = ""
if targetQuery == "" || req.URL.RawQuery == "" {
req.URL.RawQuery = targetQuery + req.URL.RawQuery
} else {
req.URL.RawQuery = targetQuery + "&" + req.URL.RawQuery
}
if setAuth != "" {
req.Header.Set("Authorization", setAuth)
}
}
return proxy
}
func buildUpstreamPath(targetPath, pathPrefix, rest string) string {
base := strings.TrimSuffix(targetPath, "/")
p := strings.Trim(pathPrefix, "/")
r := strings.Trim(rest, "/")
var segs []string
if base != "" {
segs = append(segs, base)
}
if p != "" {
segs = append(segs, p)
}
if r != "" {
segs = append(segs, r)
}
if len(segs) == 0 {
return "/"
}
out := path.Join(segs...)
if !strings.HasPrefix(out, "/") {
out = "/" + out
}
return out
}