mirror of
https://github.com/jhillyerd/inbucket.git
synced 2025-12-17 17:47:03 +00:00
web: Implement SPA compatible routing
This commit is contained in:
@@ -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 {
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
Reference in New Issue
Block a user