Mimir push reverse proxy in go
Jump to navigation
Jump to search
sqlite3 auth.db
CREATE TABLE users ( username TEXT PRIMARY KEY, password TEXT NOT NULL ); INSERT INTO users (username, password) VALUES ('admin', 'password123');
package main import ( "database/sql" "encoding/base64" "log" "net/http" "net/http/httputil" "net/url" "os" "strings" _ "github.com/mattn/go-sqlite3" ) // Database connection var db *sql.DB func main() { var err error db, err = sql.Open("sqlite3", "./auth.db") if err != nil { log.Fatalf("Failed to open database: %v", err) } defer db.Close() // Read environment variables for backend credentials and target URL backendUsername := os.Getenv("BACKEND_USERNAME") if backendUsername == "" { log.Fatal("Environment variable BACKEND_USERNAME is required") } backendPassword := os.Getenv("BACKEND_PASSWORD") if backendPassword == "" { log.Fatal("Environment variable BACKEND_PASSWORD is required") } targetURL := os.Getenv("TARGET_URL") if targetURL == "" { log.Fatal("Environment variable TARGET_URL is required") } target, err := url.Parse(targetURL) if err != nil { log.Fatalf("Invalid target URL: %v", err) } proxy := httputil.NewSingleHostReverseProxy(target) // Modify the proxy's director to add backend Basic Auth credentials originalDirector := proxy.Director proxy.Director = func(req *http.Request) { originalDirector(req) req.SetBasicAuth(backendUsername, backendPassword) } http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { if !authenticate(r) { http.Error(w, "Unauthorized", http.StatusUnauthorized) return } proxy.ServeHTTP(w, r) }) log.Println("Reverse proxy running on :8080") log.Fatal(http.ListenAndServe(":8080", nil)) } // Authenticate using Basic Auth with SQLite func authenticate(r *http.Request) bool { authHeader := r.Header.Get("Authorization") if authHeader == "" || !strings.HasPrefix(authHeader, "Basic ") { return false } decoded, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(authHeader, "Basic ")) if err != nil { return false } parts := strings.SplitN(string(decoded), ":", 2) if len(parts) != 2 { return false } username, password := parts[0], parts[1] return validateUser(username, password) } // Validate user from SQLite database func validateUser(username, password string) bool { var storedPassword string err := db.QueryRow("SELECT password FROM users WHERE username = ?", username).Scan(&storedPassword) if err != nil { return false } return password == storedPassword }
mkdir push-proxy cd push-proxy go mod init go mod tidy go build
set -a TARGET_URL=https://myprompush.example.com BACKEND_USERNAME=foo BACKEND_PASSWORD=bar
curl -u admin:password123 http://localhost:8080/api/v1/push -d '{}'