Skip to content

Instantly share code, notes, and snippets.

@mstrYoda
Created September 17, 2025 12:49
Show Gist options
  • Select an option

  • Save mstrYoda/2eb0d5032888204f5c39d6683819faa8 to your computer and use it in GitHub Desktop.

Select an option

Save mstrYoda/2eb0d5032888204f5c39d6683819faa8 to your computer and use it in GitHub Desktop.
An example http handler and proxy for mobile applications to protect their LLM keys.
package main
import (
"bytes"
"flag"
"io"
"log"
"net/http"
"net/url"
"time"
)
var (
// Command line flags
listenAddr = flag.String("addr", ":8080", "TCP address to listen on")
targetURL = flag.String("target", "", "Target URL to proxy requests to (required)")
apiKey = flag.String("api-key", "", "API key to inject for LLM provider")
authType = flag.String("auth-type", "bearer", "Authentication type: bearer, api-key, custom")
authHeader = flag.String("auth-header", "Authorization", "Header name for API key injection")
proxyKey = flag.String("proxy-key", "", "Optional key required to access this proxy")
verbose = flag.Bool("verbose", false, "Enable verbose request/response logging")
)
func main() {
flag.Parse()
if *targetURL == "" {
log.Fatal("Target URL is required. Use -target flag to specify it.")
}
if *apiKey == "" {
log.Fatal("API key is required for LLM provider access. Use -api-key flag.")
}
// Parse and validate target URL
targetU, err := url.Parse(*targetURL)
if err != nil {
log.Fatalf("Invalid target URL: %v", err)
}
if targetU.Host == "" {
log.Fatal("Target URL must include host (e.g., https://api.groq.com)")
}
log.Printf("Starting LLM proxy server on %s", *listenAddr)
log.Printf("Proxying to: %s", *targetURL)
log.Printf("Auth type: %s", *authType)
if *proxyKey != "" {
log.Printf("Proxy authentication: ENABLED")
}
// Create HTTP server
server := &http.Server{
Addr: *listenAddr,
Handler: createProxyHandler(targetU),
ReadTimeout: 30 * time.Second,
WriteTimeout: 30 * time.Second,
}
log.Printf("πŸš€ LLM Proxy ready! Send requests to: http://localhost%s", *listenAddr)
if err := server.ListenAndServe(); err != nil {
log.Fatalf("Error starting server: %v", err)
}
}
func createProxyHandler(target *url.URL) http.HandlerFunc {
// Create HTTP client with standard settings (like curl)
client := &http.Client{
Timeout: 5 * time.Minute,
Transport: &http.Transport{
DisableKeepAlives: false,
MaxIdleConns: 100,
MaxIdleConnsPerHost: 10,
IdleConnTimeout: 90 * time.Second,
},
}
return func(w http.ResponseWriter, r *http.Request) {
// Check proxy authentication if required
if *proxyKey != "" {
proxyAuth := r.Header.Get("X-Proxy-Auth")
if proxyAuth != *proxyKey {
http.Error(w, "Unauthorized: Invalid proxy key", http.StatusUnauthorized)
log.Printf("❌ Unauthorized access attempt from %s", r.RemoteAddr)
return
}
}
// Log original request
if *verbose {
log.Printf("πŸ“€ Request: %s %s", r.Method, r.URL.Path)
}
// Build target URL
targetURL := &url.URL{
Scheme: target.Scheme,
Host: target.Host,
Path: r.URL.Path,
}
// Handle query parameters
if r.URL.RawQuery != "" {
targetURL.RawQuery = r.URL.RawQuery
}
// Read request body
var body io.Reader
if r.Body != nil {
bodyBytes, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "Error reading request body", http.StatusBadRequest)
return
}
body = bytes.NewReader(bodyBytes)
if *verbose && len(bodyBytes) > 0 {
log.Printf("πŸ“€ Request Body: %s", string(bodyBytes))
}
}
// Create new request
req, err := http.NewRequest(r.Method, targetURL.String(), body)
if err != nil {
http.Error(w, "Error creating request", http.StatusInternalServerError)
return
}
// Copy headers from original request (except proxy auth)
for name, values := range r.Header {
if name == "X-Proxy-Auth" {
continue
}
for _, value := range values {
req.Header.Add(name, value)
}
}
// Set the Host header to target host
req.Host = target.Host
req.Header.Set("Host", target.Host)
// Inject API key
switch *authType {
case "bearer":
req.Header.Set(*authHeader, "Bearer "+*apiKey)
case "api-key", "api_key":
req.Header.Set(*authHeader, *apiKey)
case "custom":
req.Header.Set(*authHeader, *apiKey)
default:
req.Header.Set(*authHeader, "Bearer "+*apiKey)
}
// Remove any proxy-identifying headers
req.Header.Del("X-Forwarded-For")
req.Header.Del("X-Forwarded-Host")
req.Header.Del("X-Forwarded-Proto")
req.Header.Del("X-Real-IP")
req.Header.Del("X-Real-Ip")
if *verbose {
log.Printf("πŸ“€ Sending to: %s", targetURL.String())
log.Printf("πŸ“€ Headers:")
for name, values := range req.Header {
for _, value := range values {
log.Printf(" %s: %s", name, value)
}
}
}
// Make the request
resp, err := client.Do(req)
if err != nil {
log.Printf("❌ Error proxying request to %s: %v", target.Host, err)
http.Error(w, "Bad Gateway", http.StatusBadGateway)
return
}
defer resp.Body.Close()
// Copy response status
w.WriteHeader(resp.StatusCode)
// Copy response headers
for name, values := range resp.Header {
for _, value := range values {
w.Header().Add(name, value)
}
}
// Copy response body
_, err = io.Copy(w, resp.Body)
if err != nil {
log.Printf("❌ Error copying response: %v", err)
return
}
// Log response
statusEmoji := "βœ…"
if resp.StatusCode >= 400 {
statusEmoji = "❌"
}
log.Printf("%s %s %s -> %d", statusEmoji, r.Method, r.URL.Path, resp.StatusCode)
if *verbose {
log.Printf("πŸ“₯ Response: %d %s", resp.StatusCode, resp.Status)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment