From f493e568cbd6d07468fa03e12a6e692018c9e43b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Grill?= Date: Tue, 22 Oct 2024 09:06:23 +0200 Subject: [PATCH] multi-config support for proxy --- bindings/proxy/server/config.go | 50 +++++++++++++++++++++++++++++++++ cmd/proxy/main.go | 49 ++++++++++++++++++++------------ 2 files changed, 81 insertions(+), 18 deletions(-) create mode 100644 bindings/proxy/server/config.go diff --git a/bindings/proxy/server/config.go b/bindings/proxy/server/config.go new file mode 100644 index 0000000..c3bb15e --- /dev/null +++ b/bindings/proxy/server/config.go @@ -0,0 +1,50 @@ +package server + +import ( + "errors" + "net/http" + + "github.com/spf13/afero" +) + +type Config struct { + KeyId string `flag:"keyid,Access Key ID" reg:"KeyID" json:"keyid"` + KeySecret string `flag:"secret,Access Key Secret" reg:"KeySecret" json:"secret"` + Directory string `flag:"directory,Directory to serve" reg:"Directory" json:"directory"` + Pattern string `flag:"pattern,HTTP path pattern" reg:"Pattern" json:"pattern"` +} + +func (c *Config) Validate() error { + if c.KeyId == "" { + return errors.New("keyid is mandatory") + } + if c.KeySecret == "" { + return errors.New("secret is mandatory") + } + if c.Directory == "" { + return errors.New("directory is mandatory") + } + if c.Pattern == "" { + return errors.New("pattern is mandatory") + } + return nil +} + +func (c *Config) ToHandler() (string, http.HandlerFunc, error) { + fs := afero.NewBasePathFs(afero.NewOsFs(), c.Directory) + return c.Pattern, c.authMiddleware(Handler(fs)), nil +} + +func (c *Config) authMiddleware(next http.HandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + providedKeyID := r.Header.Get("X-Key-ID") + providedSecret := r.Header.Get("X-Secret") + + if providedKeyID != c.KeyId || providedSecret != c.KeySecret { + http.Error(w, "Unauthorized", http.StatusUnauthorized) + return + } + + next.ServeHTTP(w, r) + } +} diff --git a/cmd/proxy/main.go b/cmd/proxy/main.go index 2e925a1..0bc6a39 100644 --- a/cmd/proxy/main.go +++ b/cmd/proxy/main.go @@ -1,22 +1,20 @@ package main import ( + "encoding/json" "flag" "fmt" "net/http" "os" "github.com/balazsgrill/potatodrive/bindings/proxy/server" - "github.com/spf13/afero" ) var Version string = "0.0.0-dev" func main() { addr := flag.String("addr", ":8080", "The address to listen on for HTTP requests") - directory := flag.String("directory", ".", "The directory to serve files from") - keyID := flag.String("key-id", "", "The key ID for authentication") - secret := flag.String("secret", "", "The secret for authentication") + configfile := flag.String("config", "", "Path to the configuration file") help := flag.Bool("help", false, "Show help message") ver := flag.Bool("version", false, "Show version information") flag.Parse() @@ -31,12 +29,22 @@ func main() { os.Exit(0) } - fs := afero.NewBasePathFs(afero.NewOsFs(), *directory) - mux := http.NewServeMux() + if *configfile == "" { + fmt.Println("Please provide a configuration file") + os.Exit(1) + } - // Wrap the handler with authentication middleware - authenticatedHandler := authMiddleware(*keyID, *secret, server.Handler(fs)) - mux.HandleFunc("/", authenticatedHandler) + config := loadConfig(*configfile) + + mux := http.NewServeMux() + for _, c := range config { + pattern, handler, err := c.ToHandler() + if err != nil { + fmt.Printf("Error creating handler: %v\n", err) + os.Exit(1) + } + mux.HandleFunc(pattern, handler) + } httpserver := http.Server{ Addr: *addr, @@ -45,16 +53,21 @@ func main() { httpserver.ListenAndServe() } -func authMiddleware(keyID, secret string, next http.HandlerFunc) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - providedKeyID := r.Header.Get("X-Key-ID") - providedSecret := r.Header.Get("X-Secret") - - if providedKeyID != keyID || providedSecret != secret { - http.Error(w, "Unauthorized", http.StatusUnauthorized) - return +func loadConfig(configfile string) []server.Config { + var config []server.Config + if configfile != "" { + file, err := os.Open(configfile) + if err != nil { + fmt.Printf("Error opening config file: %v\n", err) + os.Exit(1) } + defer file.Close() - next.ServeHTTP(w, r) + decoder := json.NewDecoder(file) + if err := decoder.Decode(&config); err != nil { + fmt.Printf("Error decoding config file: %v\n", err) + os.Exit(1) + } } + return config }