Refactor routing and documentation for SPA deployment
- Updated the application to serve the SPA from the root path instead of /map/, enhancing accessibility. - Modified redirect logic to ensure backward compatibility with old /map/* URLs. - Adjusted documentation across multiple files to reflect the new routing structure and API endpoints. - Improved handling of OAuth redirects and session management in the backend. - Updated frontend configuration to align with the new base URL settings.
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -139,41 +140,69 @@ type Page struct {
|
||||
Title string `json:"title"`
|
||||
}
|
||||
|
||||
// serveMapFrontend serves the map SPA: static files from frontend, fallback to index.html for client-side routes.
|
||||
func (a *App) serveMapFrontend(rw http.ResponseWriter, req *http.Request) {
|
||||
// serveSPARoot serves the map SPA from root: static files from frontend, fallback to index.html for client-side routes.
|
||||
// Handles redirects from old /map/* URLs for backward compatibility.
|
||||
func (a *App) serveSPARoot(rw http.ResponseWriter, req *http.Request) {
|
||||
path := req.URL.Path
|
||||
if len(path) <= len("/map/") {
|
||||
path = ""
|
||||
} else {
|
||||
path = path[len("/map/"):]
|
||||
|
||||
// Redirect old /map/* URLs to flat routes
|
||||
if path == "/map" || path == "/map/" {
|
||||
http.Redirect(rw, req, "/", http.StatusFound)
|
||||
return
|
||||
}
|
||||
root := a.frontendRoot
|
||||
if path == "" {
|
||||
path = "index.html"
|
||||
if strings.HasPrefix(path, "/map/") {
|
||||
rest := path[len("/map/"):]
|
||||
switch {
|
||||
case rest == "login":
|
||||
http.Redirect(rw, req, "/login", http.StatusFound)
|
||||
return
|
||||
case rest == "profile":
|
||||
http.Redirect(rw, req, "/profile", http.StatusFound)
|
||||
return
|
||||
case rest == "admin" || strings.HasPrefix(rest, "admin/"):
|
||||
http.Redirect(rw, req, "/"+rest, http.StatusFound)
|
||||
return
|
||||
case rest == "setup":
|
||||
http.Redirect(rw, req, "/setup", http.StatusFound)
|
||||
return
|
||||
case strings.HasPrefix(rest, "character/"):
|
||||
http.Redirect(rw, req, "/"+rest, http.StatusFound)
|
||||
return
|
||||
case strings.HasPrefix(rest, "grid/"):
|
||||
http.Redirect(rw, req, "/"+rest, http.StatusFound)
|
||||
return
|
||||
}
|
||||
}
|
||||
path = filepath.Clean(path)
|
||||
if path == "." || path == ".." || (len(path) >= 2 && path[:2] == "..") {
|
||||
|
||||
// File serving: path relative to frontend root (with baseURL /, files are at root)
|
||||
filePath := strings.TrimPrefix(path, "/")
|
||||
if filePath == "" {
|
||||
filePath = "index.html"
|
||||
}
|
||||
filePath = filepath.Clean(filePath)
|
||||
if filePath == "." || filePath == ".." || strings.HasPrefix(filePath, "..") {
|
||||
http.NotFound(rw, req)
|
||||
return
|
||||
}
|
||||
tryPaths := []string{filepath.Join("map", path), path}
|
||||
// Try both root and map/ for backward compatibility with old builds
|
||||
tryPaths := []string{filePath, filepath.Join("map", filePath)}
|
||||
var f http.File
|
||||
for _, p := range tryPaths {
|
||||
var err error
|
||||
f, err = http.Dir(root).Open(p)
|
||||
f, err = http.Dir(a.frontendRoot).Open(p)
|
||||
if err == nil {
|
||||
path = p
|
||||
filePath = p
|
||||
break
|
||||
}
|
||||
}
|
||||
if f == nil {
|
||||
http.ServeFile(rw, req, filepath.Join(root, "index.html"))
|
||||
http.ServeFile(rw, req, filepath.Join(a.frontendRoot, "index.html"))
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
stat, err := f.Stat()
|
||||
if err != nil || stat.IsDir() {
|
||||
http.ServeFile(rw, req, filepath.Join(root, "index.html"))
|
||||
http.ServeFile(rw, req, filepath.Join(a.frontendRoot, "index.html"))
|
||||
return
|
||||
}
|
||||
http.ServeContent(rw, req, stat.Name(), stat.ModTime(), f)
|
||||
@@ -195,15 +224,12 @@ func (a *App) CleanChars() {
|
||||
// RegisterRoutes registers all HTTP handlers for the app.
|
||||
func (a *App) RegisterRoutes() {
|
||||
http.HandleFunc("/client/", a.client)
|
||||
|
||||
http.HandleFunc("/login", a.redirectLogin)
|
||||
http.HandleFunc("/logout", a.redirectLogout)
|
||||
http.HandleFunc("/admin", a.redirectAdmin)
|
||||
http.HandleFunc("/admin/", a.redirectAdmin)
|
||||
http.HandleFunc("/", a.redirectRoot)
|
||||
|
||||
http.HandleFunc("/map/api/", a.apiRouter)
|
||||
http.HandleFunc("/map/updates", a.watchGridUpdates)
|
||||
http.HandleFunc("/map/grids/", a.gridTile)
|
||||
http.HandleFunc("/map/", a.serveMapFrontend)
|
||||
|
||||
// SPA catch-all: must be last
|
||||
http.HandleFunc("/", a.serveSPARoot)
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ func (a *App) client(rw http.ResponseWriter, req *http.Request) {
|
||||
case "markerUpdate":
|
||||
a.uploadMarkers(rw, req)
|
||||
case "":
|
||||
http.Redirect(rw, req, "/map/", 302)
|
||||
http.Redirect(rw, req, "/", 302)
|
||||
case "checkVersion":
|
||||
if req.FormValue("version") == VERSION {
|
||||
rw.WriteHeader(200)
|
||||
|
||||
@@ -4,26 +4,6 @@ import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func (a *App) redirectRoot(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.URL.Path != "/" {
|
||||
http.NotFound(rw, req)
|
||||
return
|
||||
}
|
||||
if a.setupRequired() {
|
||||
http.Redirect(rw, req, "/map/setup", http.StatusFound)
|
||||
return
|
||||
}
|
||||
http.Redirect(rw, req, "/map/profile", http.StatusFound)
|
||||
}
|
||||
|
||||
func (a *App) redirectLogin(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.URL.Path != "/login" {
|
||||
http.NotFound(rw, req)
|
||||
return
|
||||
}
|
||||
http.Redirect(rw, req, "/map/login", http.StatusFound)
|
||||
}
|
||||
|
||||
func (a *App) redirectLogout(rw http.ResponseWriter, req *http.Request) {
|
||||
if req.URL.Path != "/logout" {
|
||||
http.NotFound(rw, req)
|
||||
@@ -33,9 +13,5 @@ func (a *App) redirectLogout(rw http.ResponseWriter, req *http.Request) {
|
||||
if s != nil {
|
||||
a.deleteSession(s)
|
||||
}
|
||||
http.Redirect(rw, req, "/map/login", http.StatusFound)
|
||||
}
|
||||
|
||||
func (a *App) redirectAdmin(rw http.ResponseWriter, req *http.Request) {
|
||||
http.Redirect(rw, req, "/map/admin", http.StatusFound)
|
||||
http.Redirect(rw, req, "/login", http.StatusFound)
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ func (a *App) oauthCallback(rw http.ResponseWriter, req *http.Request, provider
|
||||
Secure: req.TLS != nil,
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
})
|
||||
redirectTo := "/map/profile"
|
||||
redirectTo := "/profile"
|
||||
if st.RedirectURI != "" {
|
||||
if u, err := url.Parse(st.RedirectURI); err == nil && u.Path != "" && !strings.HasPrefix(u.Path, "//") {
|
||||
redirectTo = u.Path
|
||||
|
||||
Reference in New Issue
Block a user