Commit 8e5dfb9

mo khan <mo@mokhan.ca>
2025-03-04 21:35:24
feat: add API gateway to reverse proxy requests in front of two different services
1 parent 8abcc2c
Changed files (4)
bin/idp
@@ -286,7 +286,7 @@ class IdentityProvider
   end
 
   def not_found
-    [404, {}, []]
+    [404, { 'X-Backend-Server' => 'IDP' }, []]
   end
 
   def saml_params_from(request)
bin/sp
@@ -81,7 +81,7 @@ class ServiceProvider
   private
 
   def not_found
-    [404, {}, []]
+    [404, { 'X-Backend-Server' => 'SP' }, []]
   end
 
   def redirect_to(location)
cmd/gtwy/main.go
@@ -1,7 +1,51 @@
 package main
 
-import "fmt"
+import (
+	"fmt"
+	"log"
+	"net/http"
+	"net/http/httputil"
+	"strings"
+	"time"
+)
+
+func NewProxy(from, to string) http.Handler {
+	director := func(r *http.Request) {
+		log.Printf("%v (from: %v to: %v)\n", r.URL, from, to)
+		r.URL.Scheme = "http"
+		r.Host = to
+		r.URL.Host = to
+		r.URL.Path = strings.TrimPrefix(r.URL.Path, strings.TrimSuffix(from, "/*"))
+		r.URL.RawPath = strings.TrimPrefix(r.URL.RawPath, strings.TrimSuffix(from, "/*"))
+	}
+	return &httputil.ReverseProxy{
+		Director:      director,
+		Transport:     http.DefaultTransport,
+		FlushInterval: -1,
+		ErrorLog:      nil,
+		ModifyResponse: func(r *http.Response) error {
+			r.Header.Add("Via", fmt.Sprintf("%v gateway", r.Proto))
+			return nil
+		},
+		ErrorHandler: func(w http.ResponseWriter, r *http.Request, err error) {
+			log.Println(err)
+		},
+	}
+}
 
 func main() {
-	fmt.Println("hello, world!")
+	mux := http.NewServeMux()
+	mux.Handle("/idp/", NewProxy("/idp", "localhost:8282"))
+	mux.Handle("/sp/", NewProxy("/sp", "localhost:8283"))
+
+	srv := &http.Server{
+		Addr:              ":8080",
+		Handler:           mux,
+		ReadHeaderTimeout: 10 * time.Second,
+		ReadTimeout:       30 * time.Second,
+		WriteTimeout:      2 * time.Minute,
+		IdleTimeout:       5 * time.Minute,
+		ErrorLog:          log.Default(),
+	}
+	log.Fatal(srv.ListenAndServe())
 }
magefile.go
@@ -5,6 +5,7 @@ package main
 
 import (
 	"context"
+	"runtime"
 
 	"github.com/magefile/mage/mg"
 	"github.com/magefile/mage/sh"
@@ -24,12 +25,21 @@ func RunSp() error {
 	return sh.RunV("ruby", "./bin/sp")
 }
 
+// Run the API Gateway
+func RunGateway() error {
+	return sh.RunV("go", "run", "./cmd/gtwy/main.go")
+}
+
 // Open a web browser to the login page
 func Browser() error {
-	return sh.RunV("xdg-open", "http://localhost:8283/sessions/new")
+	if runtime.GOOS == "linux" {
+		return sh.RunV("xdg-open", "http://localhost:8080/sp/sessions/new")
+	} else {
+		return sh.RunV("open", "http://localhost:8080/sp/sessions/new")
+	}
 }
 
 // Run All the servers
 func Run(ctx context.Context) {
-	mg.CtxDeps(ctx, RunIdp, RunSp, Browser)
+	mg.CtxDeps(ctx, RunIdp, RunSp, RunGateway, Browser)
 }