From 16c91c1139d9f03f42c63298f2179822b8d50eb2 Mon Sep 17 00:00:00 2001 From: sanine Date: Mon, 15 May 2023 18:47:06 +0000 Subject: properly implement subpath handling --- config/config.go | 8 ++++++++ main.go | 35 +++++++++++++++++++++++------------ page/default.go | 56 ++++++++++++++++++++++++++++++++------------------------ page/page.go | 16 ++++++++-------- proxy.go | 14 +++++++------- 5 files changed, 78 insertions(+), 51 deletions(-) diff --git a/config/config.go b/config/config.go index 85c73f0..32855dc 100644 --- a/config/config.go +++ b/config/config.go @@ -29,6 +29,14 @@ type Config struct { } +type Api struct { + Prefix string + Login string + Logout string + Asset string +} + + func Load(filename string) (Config, error) { blob, err := os.ReadFile(filename) if err != nil { diff --git a/main.go b/main.go index 6e37f43..44fed27 100644 --- a/main.go +++ b/main.go @@ -16,41 +16,52 @@ import ( log "github.com/sirupsen/logrus" ) + + + func main() { - configFile := parseFlags() + configFile := parseFlags() conf := loadConfig(configFile) + api := config.Api{ + Prefix: conf.PathPrefix, + Login: "/phlox/login", + Logout: "/phlox/logout", + Asset: "/phlox/asset/", + } + sessions := auth.NewSessionContainer() - pages := loadPages(conf) + pages := loadPages(conf, api) users := getUsers(conf) // add phlox endpoints - http.HandleFunc(conf.PathPrefix + "/phlox/login", func(w http.ResponseWriter, r *http.Request) { + http.HandleFunc(api.Login, func(w http.ResponseWriter, r *http.Request) { Login(w, r, users, sessions, pages) }) - http.HandleFunc(conf.PathPrefix + "/phlox/logout", func(w http.ResponseWriter, r *http.Request) { + http.HandleFunc(api.Logout, func(w http.ResponseWriter, r *http.Request) { Logout(w, r, sessions) }) - http.HandleFunc(conf.PathPrefix + "/phlox/asset/", func(w http.ResponseWriter, r *http.Request) { - filename := strings.TrimPrefix(r.URL.Path, "/phlox/asset/") + http.HandleFunc(api.Asset, func(w http.ResponseWriter, r *http.Request) { + filename := strings.TrimPrefix(r.URL.Path, api.Asset) path := filepath.Join(conf.AssetDirectory, filename) http.ServeFile(w, r, path) }) - http.HandleFunc(conf.PathPrefix + "/", func(w http.ResponseWriter, r *http.Request) { + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/" { - w.Header().Add("Location", "/phlox/login") + w.Header().Add("Location", api.Prefix + "/phlox/login") w.WriteHeader(http.StatusTemporaryRedirect) } else { pages.ServeError404(w) + log.Errorf("404: %v", r.URL.Path) } }) // add reverse proxy endpoints for _, e := range conf.Endpoints { - addEndpoint(conf, sessions, pages, e) + addEndpoint(conf, api, sessions, pages, e) } // timer for inactivity log out @@ -70,7 +81,7 @@ func main() { func parseFlags() string { var configFile string var username string - var passwd string + var passwd string flag.StringVar(&configFile, "c", "./config.json", "the configuration file to use") flag.StringVar(&passwd, "passwd", "", "hash a password") flag.StringVar(&username, "user", "", "optional username for the JSON output of --passwd") @@ -122,8 +133,8 @@ func loadConfig(filename string) config.Config { } -func loadPages(c config.Config) page.Pages { - pages, err := page.LoadPages(c) +func loadPages(c config.Config, api config.Api) page.Pages { + pages, err := page.LoadPages(c, api) if err != nil { fmt.Fprintf(os.Stderr, "failed to load html pages: %v\n", err.Error()) os.Exit(1) diff --git a/page/default.go b/page/default.go index 822f310..9598200 100644 --- a/page/default.go +++ b/page/default.go @@ -3,12 +3,16 @@ package page import ( "strings" "text/template" + "sanine.net/git/phlox/config" ) type page struct { Title string - Body string + Head string + FormMethod string + FormAction string + FormBody string } @@ -22,7 +26,12 @@ func buildPage(p page) (string, error) { {{ .Title }} - {{ .Body }} +

{{ .Head }}

+ {{ if .FormBody }} +
+ {{ .FormBody }} +
+ {{ end }} `) @@ -41,48 +50,47 @@ func buildPage(p page) (string, error) { } -func DefaultLogin() (string, error) { +func DefaultLogin(api config.Api) (string, error) { return buildPage(page{ Title: "Login", - Body: ` -
- - -
- - -
- -
+ Head : "Log In", + FormMethod: "POST", + FormAction: api.Prefix + api.Login, + FormBody: ` + + +
+ + +
+ `, }) } -func DefaultLoggedIn() (string, error) { +func DefaultLoggedIn(api config.Api) (string, error) { return buildPage(page{ Title: "Logged In", - Body: ` -

You are logged in.

-
- -
- `, + Head: "You are logged in.", + FormMethod: "GET", + FormAction: api.Prefix + api.Logout, + FormBody: ``, }) } -func DefaultError404() (string, error) { +func DefaultError404(api config.Api) (string, error) { return buildPage(page{ Title: "404 Not Found", - Body: "

Error 404: Page not found

", + Head: "Error 404: Page not found", }) } -func DefaultError500() (string, error) { +func DefaultError500(api config.Api) (string, error) { return buildPage(page{ Title: "500 Internal Server Error", - Body: "

Error 500: Internal server error

", + Head: "Error 500: Internal server error", }) } diff --git a/page/page.go b/page/page.go index c58a344..8b44f06 100644 --- a/page/page.go +++ b/page/page.go @@ -40,7 +40,7 @@ func (p Pages) ServeError500(w http.ResponseWriter) { } -type DefaultPage func() (string, error) +type DefaultPage func(api config.Api) (string, error) func fileExists(filename string) (bool, error) { @@ -56,7 +56,7 @@ func fileExists(filename string) (bool, error) { } -func loadPage(c config.Config, filename string, fallback DefaultPage) (string, error) { +func loadPage(c config.Config, api config.Api, filename string, fallback DefaultPage) (string, error) { fullPath := filepath.Join(c.AssetDirectory, filename) exist, err := fileExists(fullPath) if err != nil { @@ -72,7 +72,7 @@ func loadPage(c config.Config, filename string, fallback DefaultPage) (string, e } else { // file does not exist // use built-in - str, err := fallback() + str, err := fallback(api) if err != nil { return "", err } @@ -81,27 +81,27 @@ func loadPage(c config.Config, filename string, fallback DefaultPage) (string, e } -func LoadPages(c config.Config) (Pages, error) { +func LoadPages(c config.Config, api config.Api) (Pages, error) { var pages Pages var err error - pages.Login, err = loadPage(c, "login.html", DefaultLogin) + pages.Login, err = loadPage(c, api, "login.html", DefaultLogin) if err != nil { return Pages{}, err } - pages.LoggedIn, err = loadPage(c, "logged_in.html", DefaultLoggedIn) + pages.LoggedIn, err = loadPage(c, api, "logged_in.html", DefaultLoggedIn) if err != nil { return Pages{}, err } - pages.Error404, err = loadPage(c, "404.html", DefaultError404) + pages.Error404, err = loadPage(c, api, "404.html", DefaultError404) if err != nil { return Pages{}, err } - pages.Error500, err = loadPage(c, "500.html", DefaultError500) + pages.Error500, err = loadPage(c, api, "500.html", DefaultError500) if err != nil { return Pages{}, err } diff --git a/proxy.go b/proxy.go index 50260f2..d5bfc88 100644 --- a/proxy.go +++ b/proxy.go @@ -19,7 +19,7 @@ type Endpoint struct { } -func addEndpoint(conf config.Config, s *auth.Sessions, pages page.Pages, e config.Endpoint) { +func addEndpoint(conf config.Config, api config.Api, s *auth.Sessions, pages page.Pages, e config.Endpoint) { log.Infof("proxying endpoint %v to %v", e.Path, e.Address) origin, err := url.Parse(e.Address) if err != nil { @@ -31,22 +31,22 @@ func addEndpoint(conf config.Config, s *auth.Sessions, pages page.Pages, e confi Origin: origin, } - http.HandleFunc(conf.PathPrefix + e.Path, func(w http.ResponseWriter, r *http.Request) { - w.Header().Add("Location", e.Path + "/") + http.HandleFunc(e.Path, func(w http.ResponseWriter, r *http.Request) { + w.Header().Add("Location", api.Prefix + e.Path + "/") w.WriteHeader(http.StatusPermanentRedirect) }) - http.HandleFunc(conf.PathPrefix + e.Path + "/", func(w http.ResponseWriter, r *http.Request) { + http.HandleFunc(e.Path + "/", func(w http.ResponseWriter, r *http.Request) { log.Infof("REQ: %v", r.URL.Path) - proxy(w, r, s, pages, end) + proxy(w, r, api, s, pages, end) }) } -func proxy(w http.ResponseWriter, r *http.Request, s *auth.Sessions, pages page.Pages, end Endpoint) { +func proxy(w http.ResponseWriter, r *http.Request, api config.Api, s *auth.Sessions, pages page.Pages, end Endpoint) { ok := authenticateRequest(r, s) if !ok { - w.Header().Set("Location", "/phlox/login") + w.Header().Set("Location", api.Prefix + api.Login) w.WriteHeader(http.StatusTemporaryRedirect) return } -- cgit v1.2.1