Skip to content

Commit

Permalink
Implement option to disable automatic NotFoundHandler registration
Browse files Browse the repository at this point in the history
  • Loading branch information
umputun committed Mar 13, 2024
1 parent 9fcd874 commit 64b7946
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 4 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,13 @@ mux.HandleFunc("/hello", routegroup.Wrap(helloHandler, loggingMiddleware, corsMi
http.ListenAndServe(":8080", mux)
```

### Automatic registration of `NotFoundHandler` as catch-all route

`routegroup` automatically registers a `NotFoundHandler` as a catch-all route, which is invoked when no other route matches the request. This handler is wrapped with all the middlewares that are associated with the group. This functionality is beneficial for applying middleware to all routes, including those that are unknown. It practically enables the use of middlewares that should operate across all routes, such as logging.

In case you want to disable this behavior, you can use the `DisableNotFoundHandler()` function.


## Real-world example

Here's an example of how `routegroup` can be used in a real-world application. The following code snippet is taken from a web service that provides a set of routes for user authentication, session management, and user management. The service also serves static files from the "assets/static" embedded file system.
Expand Down
13 changes: 9 additions & 4 deletions group.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ type Bundle struct {
basePath string // base path for the group
middlewares []func(http.Handler) http.Handler // middlewares stack

rootRegistered atomic.Value // true if the root path is registered in the mux
once sync.Once // used to register a not found handler for the root path if no / route is registered
rootRegistered atomic.Value // true if the root path is registered in the mux
once sync.Once // used to register a not found handler for the root path if no / route is registered
disableRootNotFoundHandler bool // if true, the not found handler for the root path is not registered automatically
}

// New creates a new Group.
Expand All @@ -36,12 +37,11 @@ func Mount(mux *http.ServeMux, basePath string) *Bundle {
// ServeHTTP implements the http.Handler interface
func (b *Bundle) ServeHTTP(w http.ResponseWriter, r *http.Request) {
b.once.Do(func() {
if !b.rootRegistered.Load().(bool) {
if !b.rootRegistered.Load().(bool) && !b.disableRootNotFoundHandler {
// register a not found handler for the root path if no / route is registered
// this is needed to be able to use middleware on all routes, for example logging
notFoundHandler := http.NotFoundHandler()
b.register("/", notFoundHandler.ServeHTTP)
b.rootRegistered.Store(true)
}
})

Expand Down Expand Up @@ -109,6 +109,11 @@ func (b *Bundle) Handler(r *http.Request) (h http.Handler, pattern string) {
return b.mux.Handler(r)
}

// DisableNotFoundHandler disables the automatic registration of a not found handler for the root path.
func (b *Bundle) DisableNotFoundHandler() {
b.disableRootNotFoundHandler = true
}

// Matches non-space characters, spaces, then anything, i.e. "GET /path/to/resource"
var reGo122 = regexp.MustCompile(`^(\S*)\s+(.*)$`)

Expand Down

0 comments on commit 64b7946

Please sign in to comment.