Files
Containr/internal/apwhy/gateway/proxy.go
T
Tomas Dvorak 355a97bab4 overhaul
2026-04-14 18:04:48 +02:00

86 lines
1.9 KiB
Go

package gateway
import (
"bytes"
"io"
"net/http"
"net/url"
"strings"
)
func BuildTargetURL(upstreamURL, routePrefix, requestPath, rawQuery string) (string, error) {
base, err := url.Parse(upstreamURL)
if err != nil {
return "", err
}
trimmedPrefix := routePrefix
if trimmedPrefix == "/" {
trimmedPrefix = ""
}
withoutPrefix := requestPath
if trimmedPrefix != "" && strings.HasPrefix(requestPath, trimmedPrefix) {
withoutPrefix = strings.TrimPrefix(requestPath, trimmedPrefix)
}
if !strings.HasPrefix(withoutPrefix, "/") {
withoutPrefix = "/" + withoutPrefix
}
base.Path = strings.TrimRight(base.Path, "/") + withoutPrefix
base.RawQuery = rawQuery
return base.String(), nil
}
func ProxyRequest(client *http.Client, w http.ResponseWriter, r *http.Request, targetURL string, headers map[string]string) (int, []byte, error) {
var body []byte
if r.Body != nil {
defer r.Body.Close()
payload, err := io.ReadAll(r.Body)
if err != nil {
return 0, nil, err
}
body = payload
}
upstreamReq, err := http.NewRequestWithContext(r.Context(), r.Method, targetURL, bytes.NewReader(body))
if err != nil {
return 0, nil, err
}
for key, values := range r.Header {
lower := strings.ToLower(key)
if lower == "host" || lower == "content-length" || lower == "connection" {
continue
}
for _, value := range values {
upstreamReq.Header.Add(key, value)
}
}
for key, value := range headers {
upstreamReq.Header.Set(key, value)
}
res, err := client.Do(upstreamReq)
if err != nil {
return 0, nil, err
}
defer res.Body.Close()
for key, values := range res.Header {
if strings.EqualFold(key, "transfer-encoding") || strings.EqualFold(key, "connection") {
continue
}
for _, value := range values {
w.Header().Add(key, value)
}
}
w.WriteHeader(res.StatusCode)
respBody, err := io.ReadAll(res.Body)
if err != nil {
return res.StatusCode, nil, err
}
_, _ = w.Write(respBody)
return res.StatusCode, respBody, nil
}