1
0
mirror of https://github.com/jhillyerd/inbucket.git synced 2025-12-17 09:37:02 +00:00

web: Implement SPA compatible routing

This commit is contained in:
James Hillyerd
2018-11-17 14:05:07 -08:00
parent 284dd70bc6
commit e70900dd1a
2 changed files with 48 additions and 9 deletions

View File

@@ -2,6 +2,7 @@ package web
import ( import (
"net/http" "net/http"
"os"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
@@ -30,6 +31,29 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
} }
} }
// fileHandler creates a handler that sends the named file regardless of the requested URL.
func fileHandler(name string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
f, err := os.Open(name)
if err != nil {
log.Error().Str("module", "web").Str("path", req.RequestURI).Str("file", name).Err(err).
Msg("Error opening file")
http.Error(w, "Error opening file", http.StatusInternalServerError)
return
}
defer f.Close()
d, err := f.Stat()
if err != nil {
log.Error().Str("module", "web").Str("path", req.RequestURI).Str("file", name).Err(err).
Msg("Error stating file")
http.Error(w, "Error opening file", http.StatusInternalServerError)
return
}
http.ServeContent(w, req, d.Name(), d.ModTime(), f)
})
}
// noMatchHandler creates a handler to log requests that Gorilla mux is unable to route, // noMatchHandler creates a handler to log requests that Gorilla mux is unable to route,
// returning specified statusCode to the client. // returning specified statusCode to the client.
func noMatchHandler(statusCode int, message string) http.Handler { func noMatchHandler(statusCode int, message string) http.Handler {

View File

@@ -7,6 +7,7 @@ import (
"net" "net"
"net/http" "net/http"
"net/http/pprof" "net/http/pprof"
"path/filepath"
"time" "time"
"github.com/gorilla/mux" "github.com/gorilla/mux"
@@ -47,7 +48,7 @@ func init() {
m.Set("WebSocketConnectsCurrent", ExpWebSocketConnectsCurrent) m.Set("WebSocketConnectsCurrent", ExpWebSocketConnectsCurrent)
} }
// Initialize sets up things for unit tests or the Start() method // Initialize sets up things for unit tests or the Start() method.
func Initialize( func Initialize(
conf *config.Root, conf *config.Root,
shutdownChan chan bool, shutdownChan chan bool,
@@ -57,11 +58,11 @@ func Initialize(
rootConfig = conf rootConfig = conf
globalShutdown = shutdownChan globalShutdown = shutdownChan
// NewContext() will use this DataStore for the web handlers // NewContext() will use this DataStore for the web handlers.
msgHub = mh msgHub = mh
manager = mm manager = mm
// Content Paths // Dynamic paths.
log.Info().Str("module", "web").Str("phase", "startup").Str("path", conf.Web.UIDir). log.Info().Str("module", "web").Str("phase", "startup").Str("path", conf.Web.UIDir).
Msg("Web UI content mapped") Msg("Web UI content mapped")
Router.Handle("/debug/vars", expvar.Handler()) Router.Handle("/debug/vars", expvar.Handler())
@@ -74,13 +75,27 @@ func Initialize(
log.Warn().Str("module", "web").Str("phase", "startup"). log.Warn().Str("module", "web").Str("phase", "startup").
Msg("Go pprof tools installed to /debug/pprof") Msg("Go pprof tools installed to /debug/pprof")
} }
// If no other route matches, attempt to service as UI element.
Router.PathPrefix("/").Handler(http.StripPrefix("/", http.FileServer(http.Dir(conf.Web.UIDir))))
Router.NotFoundHandler = noMatchHandler(http.StatusNotFound, "No route matches URI path")
Router.MethodNotAllowedHandler = noMatchHandler(http.StatusMethodNotAllowed,
"Method not allowed for URI path")
// Session cookie setup // Static paths.
Router.PathPrefix("/static").Handler(
http.StripPrefix("/", http.FileServer(http.Dir(conf.Web.UIDir))))
Router.Path("/favicon.png").Handler(
fileHandler(filepath.Join(conf.Web.UIDir, "favicon.png")))
// SPA managed paths.
spaHandler := fileHandler(filepath.Join(conf.Web.UIDir, "index.html"))
Router.Path("/").Handler(spaHandler)
Router.Path("/monitor").Handler(spaHandler)
Router.Path("/status").Handler(spaHandler)
Router.PathPrefix("/m/").Handler(spaHandler)
// Error handlers.
Router.NotFoundHandler = noMatchHandler(
http.StatusNotFound, "No route matches URI path")
Router.MethodNotAllowedHandler = noMatchHandler(
http.StatusMethodNotAllowed, "Method not allowed for URI path")
// Session cookie setup.
if conf.Web.CookieAuthKey == "" { if conf.Web.CookieAuthKey == "" {
log.Info().Str("module", "web").Str("phase", "startup"). log.Info().Str("module", "web").Str("phase", "startup").
Msg("Generating random cookie.auth.key") Msg("Generating random cookie.auth.key")