Reputation: 792
-- routes.go --
package main
import (
"hotelsystem/pkg/config"
"hotelsystem/pkg/handlers"
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
)
func routes(app *config.AppConfig) http.Handler {
mux := chi.NewRouter()
mux.Use(middleware.Recoverer)
mux.Use(WriteToConsole)
mux.Get("/", handlers.Repo.Home)
mux.Get("/about", handlers.Repo.About)
return mux
}
-- middleware.go --
package main
import (
"fmt"
"net/http"
)
func WriteToConsole(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Println("Hit the page")
next.ServeHTTP(w, r)
})
}
-- main.go --
package main
import (
"hotelsystem/pkg/config"
"hotelsystem/pkg/handlers"
"hotelsystem/pkg/render"
"log"
"net/http"
)
const portNumber = ":3000"
func main() {
var app config.AppConfig
tc, err := render.CreateTemplateCache()
if err != nil {
log.Fatal("Can't create templatecache", err)
}
app.TemplateCache = tc
app.UseCache = false
repo := handlers.NewRepo(&app)
handlers.NewHandlers(repo)
render.NewTemplate(&app)
// http.HandleFunc("/", handlers.Repo.Home)
// http.HandleFunc("/about", handlers.Repo.About)
// http.ListenAndServe(portNumber, nil)
srv := &http.Server{
Addr: portNumber,
Handler: routes(&app),
}
err = srv.ListenAndServe()
if err != nil {
log.Fatal(err)
}
}
I am having a hard time understanding the middleware.
I am using chi for routing.
What I didn't understand is what does that (next http.Handler
) argument in the WriteToConsole
refers to?
Does it refer to our mux router?
Also when I comment down the line next.ServeHTTP
of function writetoconsole the html is not rendered or anything? can someone explain me what does that next http.Handler
refers to and what next.serveHTTP
does?
Upvotes: 5
Views: 8780
Reputation: 38233
next
is the next handler in the "handler chain".
When you do:
mux.Use(middleware.Recoverer)
mux.Use(WriteToConsole)
mux.Get("/", handlers.Repo.Home)
mux.Get("/about", handlers.Repo.About)
You are essentially registering two "handler chains":
mux.Get("/", middleware.Recoverer(WriteToConsole(handlers.Repo.Home)))
mux.Get("/about", middleware.Recoverer(WriteToConsole(handlers.Repo.About)))
Each handler returned by the middleware function has to invoke the next
handler given to it, i.e. do next.ServeHTTP(w, r)
, if it doesn't invoke next
then the chain is broken and the rest of the handlers in that chain will be ignored.
A simplified code example may illustrate the chaining better:
type handler func()
// your handler
func f() { fmt.Println("f") }
// one middleware
func g(next handler) handler {
return func() {
fmt.Print("g.")
next()
}
}
// another middleware
func h(next handler) handler {
return func() {
fmt.Print("h.")
next()
}
}
With the above you can then do:
func main() {
h1 := h(g(f))
h1()
h2 := g(h(f))
h2()
// And you can chain as many of these as you like
// and in any order you like.
h3 := h(g(h(h(h(g(g(h(f))))))))
h3()
}
https://play.golang.org/p/4NXquYsaljr
Upvotes: 11