Context: I want a handler to throw the 404 html page even when using a FileServer function to handle views folder.
-
Problem: When I try to send a wrong path to my server (i.e: using Postman), I always get the default “404 Page not found” text instead of my custom HTML page.
-
GitHub Link for the project if you want to know how I structured my code
-
Current Implementation:
Using the default file handler from the Go Chi
documentation:
// FileServer conveniently sets up a http.FileServer handler to serve
// static files from a http.FileSystem.
func fileServerSetup(r chi.Router, path string, root http.FileSystem) {
log := config.GetLogger()
if strings.ContainsAny(path, "{}*") {
log.Error("FileServer does not permit any URL parameters.")
}
if path != "/" && path[len(path)-1] != '/' {
r.Get(path, http.RedirectHandler(path+"/", http.StatusMovedPermanently).ServeHTTP)
path += "/"
}
path += "*"
r.Get(path, func(w http.ResponseWriter, r *http.Request) {
routeContext := chi.RouteContext(r.Context())
pathPrefix := strings.TrimSuffix(routeContext.RoutePattern(), "/*")
fs := http.StripPrefix(pathPrefix, http.FileServer(root))
fs.ServeHTTP(w, r)
})
}
And this is my server’s related configuration:
type Server struct {
Router *chi.Mux
EnvConfig *config.EnvConfig
}
type ServerDefinition interface {
New() (server *Server)
MountViewsFolder() error
ApplyMiddleWares()
MountHandlers()
}
func (s *Server) New() (server *Server) {
server = &Server{}
server.Router = chi.NewRouter()
server.EnvConfig = config.LoadEnv()
pigeon.GetSmtp()
return server
}
func (s *Server) MountViewsFolder() error {
workDir, err := os.Getwd()
if err != nil {
return err
}
filesDir := http.Dir(filepath.Join(workDir, "public/views"))
fileServerSetup(s.Router, "/", filesDir)
return nil
}
func (s *Server) MountHandlers() {
s.Router.NotFound(func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "public/views/404.tmpl")
})
s.Router.Get("/swagger/*", httpSwagger.Handler(
httpSwagger.URL(
fmt.Sprintf("http://%s:%d/swagger/doc.json",
s.EnvConfig.Host,
s.EnvConfig.Port,
)),
))
// Auth
s.Router.Route("/auth", func(r chi.Router) {
r.Post("/login", auth.LoginReq)
r.With(md.RefreshVerify).Group(func(r chi.Router) {
r.Post("/refresh-token", auth.RefreshTheAccessToken)
})
})
// Sign up
s.Router.Route("/signup", func(r chi.Router) {
r.Use(middleware.AllowContentType("application/json"))
r.Post("/", signup.Register)
r.Post("/verify-email", signup.VerifyEmail)
r.Put("/reset-code", signup.ResetVerifyCode)
})
// User
s.Router.Route("/user", func(r chi.Router) {
r.Use(middleware.AllowContentType("application/json"))
r.Use(md.AccessVerify)
r.Get("/", user.GetAllUsers)
r.Put("/", user.UpdateUser)
r.With(httpin.NewInput(user.UserIdPath{})).Group(func(ru chi.Router) {
ru.Get("/{userId}", user.GetUserById)
ru.Delete("/{userId}", user.DeleteUserById)
})
})
}
- Expected Result: get the custom 404 html page I made whenever I hit a wrong URI from my backend.
- Preview of how things should have been if the above code was to work (I commented out the
MountViewsFolder
function to test the 404):