package main import ( "bytes" "encoding/json" "flag" "io" "log" "net/http" "os" "time" ) type ProxyRequest struct { Host string `json:"host"` Method string `json:"method"` Body string `json:"body"` Headers map[string]string `json:"headers"` } // Allow all CORS func enableCORS(w http.ResponseWriter) { w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS") w.Header().Set("Access-Control-Allow-Headers", "*") } func proxyHandler(w http.ResponseWriter, r *http.Request) { enableCORS(w) // Handle GET /ping request if r.URL.Path == "/ping" { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) now := time.Now() json.NewEncoder(w).Encode(map[string]int64{ "pong": now.UnixNano() / int64(time.Millisecond), }) return } // Handle preflight CORS request if r.Method == http.MethodOptions { w.WriteHeader(http.StatusOK) return } if r.Method != http.MethodPost { http.Error(w, "Only POST supported", http.StatusMethodNotAllowed) return } reqBody, err := io.ReadAll(r.Body) if err != nil { http.Error(w, "Failed to read request body: "+err.Error(), http.StatusBadRequest) return } defer r.Body.Close() var proxyReq ProxyRequest if err := json.Unmarshal(reqBody, &proxyReq); err != nil { http.Error(w, "Invalid JSON: "+err.Error(), http.StatusBadRequest) return } if proxyReq.Host == "" { http.Error(w, "'host' is required", http.StatusBadRequest) return } if proxyReq.Method == "" { proxyReq.Method = "POST" } outReq, err := http.NewRequest(proxyReq.Method, proxyReq.Host, bytes.NewBuffer([]byte(proxyReq.Body))) if err != nil { http.Error(w, "Failed to create outbound request: "+err.Error(), http.StatusInternalServerError) return } for key, value := range proxyReq.Headers { outReq.Header.Set(key, value) } log.Printf("🔁 Forwarding %s request to %s\n", proxyReq.Method, proxyReq.Host) client := &http.Client{} resp, err := client.Do(outReq) if err != nil { http.Error(w, "Request failed: "+err.Error(), http.StatusBadGateway) return } defer resp.Body.Close() for k, vv := range resp.Header { for _, v := range vv { w.Header().Add(k, v) } } w.WriteHeader(resp.StatusCode) io.Copy(w, resp.Body) } func main() { defaultPort := "9080" port := flag.String("port", os.Getenv("PORT"), "Port to run the proxy server on") flag.Parse() if *port == "" { *port = defaultPort } http.HandleFunc("/", proxyHandler) log.Printf("🟢 Proxy server listening on http://localhost:%s\n", *port) log.Fatal(http.ListenAndServe(":"+*port, nil)) } // GOOS=windows GOARCH=amd64 go build -o proxy.exe proxy.go