Skip to content

Instantly share code, notes, and snippets.

@gauravds
Last active March 26, 2025 11:55
Show Gist options
  • Save gauravds/99fe316cfaaa5e5e56136613bd7f90db to your computer and use it in GitHub Desktop.
Save gauravds/99fe316cfaaa5e5e56136613bd7f90db to your computer and use it in GitHub Desktop.

Revisions

  1. gauravds revised this gist Mar 26, 2025. 1 changed file with 12 additions and 0 deletions.
    12 changes: 12 additions & 0 deletions proxy.go
    Original file line number Diff line number Diff line change
    @@ -8,6 +8,7 @@ import (
    "log"
    "net/http"
    "os"
    "time"
    )

    type ProxyRequest struct {
    @@ -26,6 +27,17 @@ func enableCORS(w http.ResponseWriter) {

    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 {
  2. gauravds created this gist Mar 25, 2025.
    106 changes: 106 additions & 0 deletions proxy.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,106 @@
    package main

    import (
    "bytes"
    "encoding/json"
    "flag"
    "io"
    "log"
    "net/http"
    "os"
    )

    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 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