106 lines
2.2 KiB
Go
106 lines
2.2 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/http/httputil"
|
|
"net/url"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/caarlos0/env/v11"
|
|
)
|
|
|
|
var cfg config
|
|
|
|
type config struct {
|
|
BaseURL string `env:"BASE_URL"`
|
|
Port int `env:"PORT"`
|
|
}
|
|
|
|
func createProxy(target *url.URL) func(http.ResponseWriter, *http.Request) {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
r.Host = target.Host
|
|
r.URL.Scheme = target.Scheme
|
|
r.URL.Host = target.Host
|
|
|
|
lrw := &LoggingResponseWriter{ResponseWriter: w, body: new(bytes.Buffer)}
|
|
proxy := httputil.NewSingleHostReverseProxy(target)
|
|
|
|
startTime := time.Now()
|
|
recorder := httptest.NewRecorder()
|
|
proxy.ServeHTTP(recorder, r)
|
|
|
|
responseBody := recorder.Body.Bytes()
|
|
|
|
var jsonResponse map[string]interface{}
|
|
err := json.Unmarshal(responseBody, &jsonResponse)
|
|
if err != nil {
|
|
log.Printf("Error unmarshalling JSON response: %v", err)
|
|
lrw.Write(responseBody)
|
|
return
|
|
}
|
|
|
|
// Add your metrics metadata here
|
|
jsonResponse["metrics"] = map[string]interface{}{
|
|
"requestPath": r.URL.Path,
|
|
"statusCode": recorder.Code,
|
|
"responseTime": time.Since(startTime).Milliseconds(),
|
|
// Add more metrics as needed
|
|
}
|
|
|
|
modifiedResponseBody, err := json.Marshal(jsonResponse)
|
|
if err != nil {
|
|
log.Printf("Error marshalling modified JSON response: %v", err)
|
|
lrw.Write(responseBody)
|
|
return
|
|
}
|
|
|
|
for name, values := range recorder.Header() {
|
|
for _, value := range values {
|
|
w.Header().Add(name, value)
|
|
}
|
|
}
|
|
|
|
w.WriteHeader(recorder.Code)
|
|
lrw.Write(modifiedResponseBody)
|
|
|
|
log.Printf("Response with metrics: %s", lrw.Body())
|
|
}
|
|
}
|
|
|
|
type LoggingResponseWriter struct {
|
|
http.ResponseWriter
|
|
body *bytes.Buffer
|
|
}
|
|
|
|
func (lrw *LoggingResponseWriter) Write(b []byte) (int, error) {
|
|
lrw.body.Write(b)
|
|
return lrw.ResponseWriter.Write(b)
|
|
}
|
|
|
|
func (lrw *LoggingResponseWriter) Body() string {
|
|
return lrw.body.String()
|
|
}
|
|
|
|
func main() {
|
|
env.Parse(&cfg)
|
|
|
|
targetURL, err := url.Parse(cfg.BaseURL)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
http.HandleFunc("/", createProxy(targetURL))
|
|
|
|
log.Printf("Starting proxy server on :%s", strconv.Itoa(cfg.Port))
|
|
err = http.ListenAndServe(fmt.Sprintf(":%s", strconv.Itoa(cfg.Port)), nil)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|