How to run a function before all handlers?
Asked Answered
R

3

2

Is it possible to execute a function before any handlers in a web application using the net/http package or any of the gorilla libraries?

This would be useful, for instance, to check if the incoming request is from a blacklisted IP address before proceeding to the actual request handlers.

Rameses answered 21/1, 2015 at 15:30 Comment(1)
What you want is called Middleware in this context, also see alexedwards.net/blog/making-and-using-middlewareForegone
L
7

Create a handler that invokes another handler after checking the IP address:

type checker struct {
   h http.Handler
}

func (c checker) ServeHTTP(w http.ResponseWriter, r *http.Request) {
   if blackListed(r.RemoteAddr) {
      http.Error(w, "not authorized", http.StatusForbidden)
      return
   }
   c.h.ServeHTTP(w, r)
}

Pass this handler to ListenAndServe instead of your original handler. For example, if you had:

err := http.ListenAndServe(addr, mux)

change the code to

err := http.ListenAndServe(addr, checker{mux})

This also applies to all the variations of ListenAndServe. It works with http.ServeMux, Gorilla mux and other routers.

Lamprey answered 21/1, 2015 at 15:40 Comment(0)
F
0

To run a function (middleware) before each handler, i will use in this example gorilla/mux.
I created a function (middleware) that logs some of the request infos

func main() {

r := mux.NewRouter()

// Handlers
r.HandleFunc("/hello", helloWorldHandler)

// use middleware to log all requests
r.Use(logMiddleware)


http.ListenAndServe(":8080", r)
}

func logMiddleware(next http.Handler) http.Handler {
     return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

     // add your middleware code here
     log.Printf("received request for %s from %s", r.URL.Path, r.RemoteAddr)

     // call the next handler in the chain
     next.ServeHTTP(w, r)
})}

func helloHandler(w http.ResponseWriter, r *http.Request) {
     fmt.Println("Hello world!")
}
Forensics answered 6/3, 2023 at 16:31 Comment(0)
M
-1

If you want to use the default muxer, which i find is common, you can create middleware like so:

func mustBeLoggedIn(handler func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
    return func(w http.ResponseWriter, r *http.Request) {
        // Am i logged in?
        if ...not logged in... {
            http.Error(w, err.Error(), http.StatusUnauthorized)
            return
        }
        // Pass through to the original handler.
        handler(w, r)
    }
}

Use it like so:

http.HandleFunc("/some/priveliged/action", mustBeLoggedIn(myVanillaHandler))
http.ListenAndServe(":80", nil)
Moise answered 29/5, 2019 at 0:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.