mirror of
https://github.com/Dvorinka/Containr.git
synced 2026-06-03 20:12:58 +00:00
86 lines
1.9 KiB
Go
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
|
|
}
|