package main import ( "log" "net/http" "net/http/httputil" "net/url" ) // startProxy starts an HTTP reverse proxy that forwards requests to workers. // It acquires a worker from the pool for each request and releases it when done. func startProxy(listenAddr string, pool *WorkerPool) { handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Acquire a worker (blocks if none available) workerAddr, ok := pool.Acquire() if !ok { http.Error(w, "Service unavailable", http.StatusServiceUnavailable) return } // Ensure we release the worker when done defer pool.Release(workerAddr) // Create reverse proxy to the worker targetURL, err := url.Parse("http://" + workerAddr) if err != nil { log.Printf("[proxy] Failed to parse worker URL %s: %v", workerAddr, err) http.Error(w, "Internal server error", http.StatusInternalServerError) return } proxy := httputil.NewSingleHostReverseProxy(targetURL) // Custom error handler proxy.ErrorHandler = func(w http.ResponseWriter, r *http.Request, err error) { log.Printf("[proxy] Error proxying to %s: %v", workerAddr, err) http.Error(w, "Bad gateway", http.StatusBadGateway) } log.Printf("[proxy] %s %s -> %s", r.Method, r.URL.Path, workerAddr) proxy.ServeHTTP(w, r) }) log.Printf("[proxy] Listening on %s", listenAddr) if err := http.ListenAndServe(listenAddr, handler); err != nil { log.Fatalf("[proxy] Failed to start: %v", err) } }