📦 Update dependencies and add request tracing with UUID
This commit is contained in:
@@ -5,3 +5,5 @@ go 1.24.3
|
|||||||
require github.com/joho/godotenv v1.5.1
|
require github.com/joho/godotenv v1.5.1
|
||||||
|
|
||||||
require github.com/pelletier/go-toml/v2 v2.3.0
|
require github.com/pelletier/go-toml/v2 v2.3.0
|
||||||
|
|
||||||
|
require github.com/google/uuid v1.6.0
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||||
github.com/pelletier/go-toml/v2 v2.3.0 h1:k59bC/lIZREW0/iVaQR8nDHxVq8OVlIzYCOJf421CaM=
|
github.com/pelletier/go-toml/v2 v2.3.0 h1:k59bC/lIZREW0/iVaQR8nDHxVq8OVlIzYCOJf421CaM=
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
"github.com/pelletier/go-toml/v2"
|
"github.com/pelletier/go-toml/v2"
|
||||||
)
|
)
|
||||||
@@ -71,13 +72,15 @@ func main() {
|
|||||||
|
|
||||||
func handleProxy(cfg Config) http.HandlerFunc {
|
func handleProxy(cfg Config) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Println("Handle proxy: ", r.URL)
|
requestId := uuid.New().String()
|
||||||
|
|
||||||
|
log.Println("Handle proxy: ", requestId, r.URL)
|
||||||
if r.URL.Path == "/health" {
|
if r.URL.Path == "/health" {
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
proxyReq := cloneRequest(r, cfg.UpstreamURL)
|
proxyReq := cloneRequest(requestId, r, cfg.UpstreamURL)
|
||||||
|
|
||||||
if cfg.APIKey != "" {
|
if cfg.APIKey != "" {
|
||||||
proxyReq.Header.Set("Authorization", "Bearer "+cfg.APIKey)
|
proxyReq.Header.Set("Authorization", "Bearer "+cfg.APIKey)
|
||||||
@@ -90,7 +93,7 @@ func handleProxy(cfg Config) http.HandlerFunc {
|
|||||||
|
|
||||||
resp, err := client.Do(proxyReq)
|
resp, err := client.Do(proxyReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println("Upstream error: ", err)
|
log.Println("Upstream error: ", requestId, err)
|
||||||
http.Error(w, fmt.Sprintf("upstream error: %v", err), http.StatusBadGateway)
|
http.Error(w, fmt.Sprintf("upstream error: %v", err), http.StatusBadGateway)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -102,18 +105,18 @@ func handleProxy(cfg Config) http.HandlerFunc {
|
|||||||
w.WriteHeader(resp.StatusCode)
|
w.WriteHeader(resp.StatusCode)
|
||||||
|
|
||||||
isStreamingRequest := isStreaming(resp)
|
isStreamingRequest := isStreaming(resp)
|
||||||
log.Println("Request streaming: ", isStreamingRequest)
|
log.Println("Request streaming: ", requestId, isStreamingRequest)
|
||||||
|
|
||||||
if !isStreamingRequest {
|
if !isStreamingRequest {
|
||||||
io.Copy(w, resp.Body)
|
io.Copy(w, resp.Body)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
handleStream(w, resp.Body, cfg)
|
handleStream(requestId, w, resp.Body, cfg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func cloneRequest(r *http.Request, upstreamURL string) *http.Request {
|
func cloneRequest(requestId string, r *http.Request, upstreamURL string) *http.Request {
|
||||||
upstream, _ := url.Parse(upstreamURL)
|
upstream, _ := url.Parse(upstreamURL)
|
||||||
|
|
||||||
proxyReq := r.Clone(context.Background())
|
proxyReq := r.Clone(context.Background())
|
||||||
@@ -125,7 +128,7 @@ func cloneRequest(r *http.Request, upstreamURL string) *http.Request {
|
|||||||
}
|
}
|
||||||
proxyReq.Host = upstream.Host
|
proxyReq.Host = upstream.Host
|
||||||
|
|
||||||
log.Println("Upstream proxy: ", proxyReq.URL)
|
log.Println("Upstream proxy: ", requestId, proxyReq.URL)
|
||||||
if val := r.Header.Get("Content-Type"); val != "" {
|
if val := r.Header.Get("Content-Type"); val != "" {
|
||||||
proxyReq.Header.Set("Content-Type", val)
|
proxyReq.Header.Set("Content-Type", val)
|
||||||
}
|
}
|
||||||
@@ -144,14 +147,17 @@ func isStreaming(resp *http.Response) bool {
|
|||||||
strings.Contains(ct, "stream")
|
strings.Contains(ct, "stream")
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleStream(w io.Writer, body io.Reader, cfg Config) {
|
func handleStream(requestId string, w io.Writer, body io.Reader, cfg Config) {
|
||||||
reader := bufio.NewReader(body)
|
reader := bufio.NewReader(body)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
line, err := reader.ReadString('\n')
|
line, err := reader.ReadString('\n')
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != io.EOF {
|
if err != io.EOF {
|
||||||
|
log.Println("Stream error: ", requestId, err)
|
||||||
fmt.Fprintf(os.Stderr, "stream error: %v\n", err)
|
fmt.Fprintf(os.Stderr, "stream error: %v\n", err)
|
||||||
|
} else {
|
||||||
|
log.Println("Stream end: ", requestId)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -161,12 +167,12 @@ func handleStream(w io.Writer, body io.Reader, cfg Config) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
processChunk(w, line, cfg)
|
processChunk(requestId, w, line, cfg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func processChunk(w io.Writer, line string, cfg Config) {
|
func processChunk(requestId string, w io.Writer, line string, cfg Config) {
|
||||||
log.Println("Process chunk: ", line)
|
log.Println("Process chunk: ", requestId, line)
|
||||||
if strings.HasPrefix(line, "data: ") {
|
if strings.HasPrefix(line, "data: ") {
|
||||||
data := strings.TrimPrefix(line, "data: ")
|
data := strings.TrimPrefix(line, "data: ")
|
||||||
if data == "[DONE]" {
|
if data == "[DONE]" {
|
||||||
|
|||||||
Reference in New Issue
Block a user