Fix 404 handler route

This commit is contained in:
2026-02-07 18:29:27 +01:00
parent 2b395a94e6
commit 624746f34b
3 changed files with 79 additions and 20 deletions

View File

@@ -279,8 +279,8 @@ func (s *Server) init() error {
} }
} }
// Custom 404 handler for unmatched routes // 404 handler for pages and API routes
s.router.NotFound(func(rw http.ResponseWriter, r *http.Request) { notFoundHandler := func(rw http.ResponseWriter, r *http.Request) {
if strings.HasPrefix(r.URL.Path, "/api/") || strings.HasPrefix(r.URL.Path, "/userapi/") || if strings.HasPrefix(r.URL.Path, "/api/") || strings.HasPrefix(r.URL.Path, "/userapi/") ||
strings.HasPrefix(r.URL.Path, "/frontend/") || strings.HasPrefix(r.URL.Path, "/config/") { strings.HasPrefix(r.URL.Path, "/frontend/") || strings.HasPrefix(r.URL.Path, "/config/") {
rw.Header().Set("Content-Type", "application/json") rw.Header().Set("Content-Type", "application/json")
@@ -291,14 +291,13 @@ func (s *Server) init() error {
}) })
return return
} }
rw.Header().Set("Content-Type", "text/html; charset=utf-8")
rw.WriteHeader(http.StatusNotFound) rw.WriteHeader(http.StatusNotFound)
web.RenderTemplate(rw, "message.tmpl", &web.Page{ web.RenderTemplate(rw, "404.tmpl", &web.Page{
Title: "Not Found", Title: "Page Not Found",
MsgType: "alert-warning", Build: buildInfo,
Message: "The requested page was not found.",
Build: buildInfo,
}) })
}) }
if config.Keys.EmbedStaticFiles { if config.Keys.EmbedStaticFiles {
if i, err := os.Stat("./var/img"); err == nil { if i, err := os.Stat("./var/img"); err == nil {
@@ -307,9 +306,26 @@ func (s *Server) init() error {
s.router.Handle("/img/*", http.StripPrefix("/img/", http.FileServer(http.Dir("./var/img")))) s.router.Handle("/img/*", http.StripPrefix("/img/", http.FileServer(http.Dir("./var/img"))))
} }
} }
s.router.Handle("/*", http.StripPrefix("/", web.ServeFiles())) fileServer := http.StripPrefix("/", web.ServeFiles())
s.router.Handle("/*", http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
if web.StaticFileExists(r.URL.Path) {
fileServer.ServeHTTP(rw, r)
return
}
notFoundHandler(rw, r)
}))
} else { } else {
s.router.Handle("/*", http.FileServer(http.Dir(config.Keys.StaticFiles))) staticDir := http.Dir(config.Keys.StaticFiles)
fileServer := http.FileServer(staticDir)
s.router.Handle("/*", http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
f, err := staticDir.Open(r.URL.Path)
if err == nil {
f.Close()
fileServer.ServeHTTP(rw, r)
return
}
notFoundHandler(rw, r)
}))
} }
return nil return nil

View File

@@ -1,10 +1,39 @@
{{template "base.tmpl" .}} <!DOCTYPE html>
{{define "content"}} <html lang="en">
<div class="row"> <head>
<div class="col"> <meta http-equiv="content-type" content="text/html; charset=utf-8" />
<div class="alert alert-error" role="alert"> <meta name='viewport' content='width=device-width,initial-scale=1'>
404: Not found <title>{{.Title}}</title>
</div> <link rel='icon' type='image/png' href='/favicon.png'>
</div> <link rel="stylesheet" href="/bootstrap.min.css">
</div> </head>
{{end}} <body>
<header>
<nav class="navbar navbar-expand-lg navbar-light fixed-top bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="/">
<img style="height: 30px;" alt="ClusterCockpit Logo" src="/img/logo.png" class="d-inline-block align-top">
</a>
</div>
</nav>
</header>
<main>
<section class="content-section">
<div class="container">
<div class="row justify-content-center">
<div class="col-6 text-center">
<div class="card mt-5">
<div class="card-body p-5">
<h1 class="display-1 text-muted">404</h1>
<h2 class="mb-3">Page Not Found</h2>
<p class="text-muted mb-4">The page you are looking for does not exist or has been moved.</p>
<a href="/" class="btn btn-primary">Back to Home</a>
</div>
</div>
</div>
</div>
</div>
</section>
</main>
</body>
</html>

View File

@@ -186,6 +186,16 @@ func ServeFiles() http.Handler {
return http.FileServer(http.FS(publicFiles)) return http.FileServer(http.FS(publicFiles))
} }
// StaticFileExists checks whether a static file exists in the embedded frontend FS.
func StaticFileExists(path string) bool {
path = strings.TrimPrefix(path, "/")
if path == "" {
return false
}
_, err := fs.Stat(frontendFiles, "frontend/public/"+path)
return err == nil
}
//go:embed templates/* //go:embed templates/*
var templateFiles embed.FS var templateFiles embed.FS
@@ -201,6 +211,10 @@ func init() {
return nil return nil
} }
if path == "templates/404.tmpl" {
templates[strings.TrimPrefix(path, "templates/")] = template.Must(template.ParseFS(templateFiles, path))
return nil
}
if path == "templates/login.tmpl" { if path == "templates/login.tmpl" {
if util.CheckFileExists("./var/login.tmpl") { if util.CheckFileExists("./var/login.tmpl") {
cclog.Info("overwrite login.tmpl with local file") cclog.Info("overwrite login.tmpl with local file")