Golang net/http и Gorilla: запустить код перед обработчиком

Возможно ли использовать пакет net/http и / или любую из библиотек gorilla, чтобы какой-либо код выполнялся на КАЖДОМ URL, прежде чем перейти к обработчику? Например, чтобы проверить, идет ли соединение с черного IP-адреса в списке?

3 ответа

Создайте обработчик, который вызывает другой обработчик после проверки IP-адреса:

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)
}

Передайте этот обработчик ListenAndServe вместо вашего исходного обработчика. Например, если у вас было:

err := http.ListenAndServe(addr, mux)

изменить код на

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

Это также относится ко всем вариантам ListenAndServe. Работает с http.ServeMux, Gorilla mux и другими роутерами.

Чтобы запустить функцию ( промежуточное программное обеспечение ) перед каждым обработчиком, в этом примере я буду использовать gorilla/mux.
Я создал функцию ( промежуточное программное обеспечение ), которая регистрирует некоторую информацию о запросе.

      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!")
}

Если вы хотите использовать мультиплексор по умолчанию, который, как я считаю, является обычным, вы можете создать промежуточное ПО следующим образом:

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)
    }
}

Используйте это так:

http.HandleFunc("/some/priveliged/action", mustBeLoggedIn(myVanillaHandler))
http.ListenAndServe(":80", nil)
Другие вопросы по тегам