diff --git a/cmd/cc-backend/server.go b/cmd/cc-backend/server.go index 7e2b3ed3..250d4860 100644 --- a/cmd/cc-backend/server.go +++ b/cmd/cc-backend/server.go @@ -279,8 +279,8 @@ func (s *Server) init() error { } } - // Custom 404 handler for unmatched routes - s.router.NotFound(func(rw http.ResponseWriter, r *http.Request) { + // 404 handler for pages and API routes + notFoundHandler := func(rw http.ResponseWriter, r *http.Request) { 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/") { rw.Header().Set("Content-Type", "application/json") @@ -291,14 +291,13 @@ func (s *Server) init() error { }) return } + rw.Header().Set("Content-Type", "text/html; charset=utf-8") rw.WriteHeader(http.StatusNotFound) - web.RenderTemplate(rw, "message.tmpl", &web.Page{ - Title: "Not Found", - MsgType: "alert-warning", - Message: "The requested page was not found.", - Build: buildInfo, + web.RenderTemplate(rw, "404.tmpl", &web.Page{ + Title: "Page Not Found", + Build: buildInfo, }) - }) + } if config.Keys.EmbedStaticFiles { 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("/*", 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 { - 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 diff --git a/web/templates/404.tmpl b/web/templates/404.tmpl index 1bddd58b..b27599d0 100644 --- a/web/templates/404.tmpl +++ b/web/templates/404.tmpl @@ -1,10 +1,39 @@ -{{template "base.tmpl" .}} -{{define "content"}} -
-
- -
-
-{{end}} + + + + + + {{.Title}} + + + + +
+ +
+
+
+
+
+
+
+
+

404

+

Page Not Found

+

The page you are looking for does not exist or has been moved.

+ Back to Home +
+
+
+
+
+
+
+ + diff --git a/web/web.go b/web/web.go index f3185abc..d24e8fc7 100644 --- a/web/web.go +++ b/web/web.go @@ -186,6 +186,16 @@ func ServeFiles() http.Handler { 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/* var templateFiles embed.FS @@ -201,6 +211,10 @@ func init() { 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 util.CheckFileExists("./var/login.tmpl") { cclog.Info("overwrite login.tmpl with local file")