edge proxy support + updated readme

This commit is contained in:
stefanodvx 2025-04-20 01:00:50 +02:00
parent 8d57b97b0f
commit 6f5e792b01
5 changed files with 222 additions and 86 deletions

111
util/edgeproxy.go Normal file
View file

@ -0,0 +1,111 @@
package util
import (
"bytes"
"encoding/json"
"fmt"
"govd/models"
"io"
"net/http"
"net/url"
"os"
"sync"
"time"
)
var (
edgeProxyClient *EdgeProxyClient
edgeProxyClientOnce sync.Once
)
type EdgeProxyClient struct {
*http.Client
}
func GetEdgeProxyClient() *EdgeProxyClient {
edgeProxyClientOnce.Do(func() {
edgeProxyClient = &EdgeProxyClient{
Client: &http.Client{
Transport: baseTransport,
Timeout: 60 * time.Second,
},
}
})
return edgeProxyClient
}
func (c *EdgeProxyClient) Do(req *http.Request) (*http.Response, error) {
proxyURL := os.Getenv("EDGE_PROXY_URL")
if proxyURL == "" {
return nil, fmt.Errorf("EDGE_PROXY_URL environment variable is not set")
}
targetURL := req.URL.String()
encodedURL := url.QueryEscape(targetURL)
proxyURLWithParam := proxyURL + "?url=" + encodedURL
var bodyBytes []byte
var err error
if req.Body != nil {
bodyBytes, err = io.ReadAll(req.Body)
if err != nil {
return nil, fmt.Errorf("error reading request body: %w", err)
}
req.Body.Close()
req.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
}
proxyReq, err := http.NewRequest(
req.Method,
proxyURLWithParam,
bytes.NewBuffer(bodyBytes),
)
if err != nil {
return nil, fmt.Errorf("error creating proxy request: %w", err)
}
for name, values := range req.Header {
for _, value := range values {
proxyReq.Header.Add(name, value)
}
}
proxyResp, err := c.Client.Do(proxyReq)
if err != nil {
return nil, fmt.Errorf("proxy request failed: %w", err)
}
defer proxyResp.Body.Close()
body, err := io.ReadAll(proxyResp.Body)
if err != nil {
return nil, fmt.Errorf("error reading proxy response: %w", err)
}
var response models.ProxyResponse
if err := json.Unmarshal(body, &response); err != nil {
return nil, fmt.Errorf("error parsing proxy response: %w", err)
}
resp := &http.Response{
StatusCode: response.StatusCode,
Status: fmt.Sprintf("%d %s", response.StatusCode, http.StatusText(response.StatusCode)),
Body: io.NopCloser(bytes.NewBufferString(response.Text)),
Header: make(http.Header),
Request: req,
}
parsedResponseURL, err := url.Parse(response.URL)
if err != nil {
return nil, fmt.Errorf("error parsing response URL: %w", err)
}
resp.Request.URL = parsedResponseURL
for name, value := range response.Headers {
resp.Header.Set(name, value)
}
for _, cookie := range response.Cookies {
resp.Header.Add("Set-Cookie", cookie)
}
return resp, nil
}

View file

@ -10,34 +10,28 @@ import (
var (
httpSession *http.Client
httpSessionOnce sync.Once
baseTransport = &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext,
ForceAttemptHTTP2: true,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 5 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
MaxIdleConnsPerHost: 100,
MaxConnsPerHost: 100,
ResponseHeaderTimeout: 10 * time.Second,
DisableCompression: false,
}
)
func GetHTTPSession() *http.Client {
httpSessionOnce.Do(func() {
transport := &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext,
ForceAttemptHTTP2: true,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 5 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
MaxIdleConnsPerHost: 100,
MaxConnsPerHost: 100,
ResponseHeaderTimeout: 10 * time.Second,
DisableCompression: false,
}
httpSession = &http.Client{
Transport: transport,
Transport: baseTransport,
Timeout: 60 * time.Second,
}
})