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)