package handlers import ( "io" "net/http" "os" "github.com/gin-gonic/gin" ) type FunctionProxyHandler struct { supabaseURL string anonKey string } func NewFunctionProxyHandler() *FunctionProxyHandler { return &FunctionProxyHandler{ supabaseURL: os.Getenv("SUPABASE_URL"), anonKey: os.Getenv("SUPABASE_SERVICE_ROLE_KEY"), // Using service role to bypass RLS/Auth if needed, or stick to Anon } } func (h *FunctionProxyHandler) ProxyFunction(c *gin.Context) { functionName := c.Param("name") if functionName == "" { c.JSON(http.StatusBadRequest, gin.H{"error": "Function name is required"}) return } targetURL := h.supabaseURL + "/functions/v1/" + functionName // Create new request req, err := http.NewRequest(c.Request.Method, targetURL, c.Request.Body) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create request"}) return } // Copy headers for k, v := range c.Request.Header { req.Header[k] = v } // Override Host and add Supabase Auth req.Header.Set("Authorization", "Bearer "+h.anonKey) req.Header.Set("apikey", h.anonKey) client := &http.Client{} resp, err := client.Do(req) if err != nil { c.JSON(http.StatusBadGateway, gin.H{"error": "Failed to call Supabase function"}) return } defer resp.Body.Close() // Copy response headers for k, v := range resp.Header { c.Writer.Header()[k] = v } c.Writer.WriteHeader(resp.StatusCode) io.Copy(c.Writer, resp.Body) }