Gorilla mux自定义中间件

huangapple go评论96阅读模式
英文:

Gorilla mux custom middleware

问题

我正在使用gorilla mux来管理路由。我需要集成一个中间件来处理每个请求。

例如:

package main

import (
	"fmt"
	"github.com/gorilla/mux"
	"log"
	"net/http"
	"strconv"
)

func HomeHandler(response http.ResponseWriter, request *http.Request) {

	fmt.Fprintf(response, "Hello home")
}

func Middleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(response http.ResponseWriter, request *http.Request) {
		// 在这里执行中间件逻辑
		log.Println("Executing middleware")
		next.ServeHTTP(response, request)
	})
}

func main() {

	port := 3000
	portstring := strconv.Itoa(port)

	r := mux.NewRouter()
	r.HandleFunc("/", HomeHandler)
	http.Handle("/", Middleware(r))

	log.Print("Listening on port " + portstring + " ... ")
	err := http.ListenAndServe(":"+portstring, nil)
	if err != nil {
		log.Fatal("ListenAndServe error: ", err)
	}
}

每个传入的请求都会经过中间件。你可以通过创建一个中间件函数来实现。在这个函数中,你可以执行你想要的中间件逻辑,然后调用next.ServeHTTP(response, request)来将请求传递给下一个处理程序。

更新

我将与gorilla/sessions一起使用,他们说:

重要提示:如果你不使用gorilla/mux,你需要使用context.ClearHandler来包装你的处理程序,否则会导致内存泄漏!在调用http.ListenAndServe时,一种简单的方法是包装顶级mux:

你可以使用context.ClearHandler来解决这个问题。在调用http.ListenAndServe时,将顶级mux包装在context.ClearHandler中即可。

英文:

I am using gorilla mux for manage routing. What I am missing is to integrate a middleware between every request.

For example

package main

import (
	"fmt"
	"github.com/gorilla/mux"
	"log"
	"net/http"
	"strconv"
)

func HomeHandler(response http.ResponseWriter, request *http.Request) {

	fmt.Fprintf(response, "Hello home")
}

func main() {

	port := 3000
	portstring := strconv.Itoa(port)

	r := mux.NewRouter()
	r.HandleFunc("/", HomeHandler)
	http.Handle("/", r)

	log.Print("Listening on port " + portstring + " ... ")
	err := http.ListenAndServe(":"+portstring, nil)
	if err != nil {
		log.Fatal("ListenAndServe error: ", err)
	}
}

Every incoming request should pass through the middleware. How can I integrate here a midleware?

Update

I will use it in combination with gorilla/sessions, and they say:

> Important Note: If you aren't using gorilla/mux, you need to wrap your
> handlers with context.ClearHandler as or else you will leak memory! An
> easy way to do this is to wrap the top-level mux when calling
> http.ListenAndServe:

How can I prevent this scenario?

答案1

得分: 74

只需在Go中创建一个包装器即可,非常简单:

func HomeHandler(response http.ResponseWriter, request *http.Request) {
    fmt.Fprintf(response, "Hello home")
}

func Middleware(h http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        log.Println("middleware", r.URL)
        h.ServeHTTP(w, r)
    })
}

func main() {
    r := mux.NewRouter()
    r.HandleFunc("/", HomeHandler)
    http.Handle("/", Middleware(r))
}

这段代码创建了一个名为HomeHandler的函数,用于处理主页请求。Middleware函数是一个中间件,用于在处理请求之前和之后执行一些操作。main函数是程序的入口点,它创建了一个路由器r,并将HomeHandler函数与根路径"/"进行绑定。然后,通过Middleware函数将路由器作为参数传递给http.Handle函数,以便在处理请求时应用中间件。

英文:

Just create a wrapper, it's rather easy in Go:

func HomeHandler(response http.ResponseWriter, request *http.Request) {

	fmt.Fprintf(response, "Hello home")
}

func Middleware(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		log.Println("middleware", r.URL)
		h.ServeHTTP(w, r)
	})
}
func main() {
	r := mux.NewRouter()
	r.HandleFunc("/", HomeHandler)
	http.Handle("/", Middleware(r))
}

答案2

得分: 25

Mux有一种官方的方法来实现中间件,可以参考以下示例代码:

// 一个普通的中间件
func Middleware(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// 在处理程序之前做一些事情
		h.ServeHTTP(w, r)
		// 在处理程序之后做一些事情
	})
}

// 如果你想将数据传递给中间件
func Middleware2(s string) mux.MiddlewareFunc {
	return func(h http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			// 做一些事情
			fmt.Println(s)
			h.ServeHTTP(w, r)
		})
	}
}

func main() {
	router := mux.NewRouter()

	router.Use(Middleware)
	// 你也可以将中间件应用于子路由器
	subRouter := router.PathPrefix("/sub_router/").Subrouter()
	subRouter.Use(Middleware2("somePrams"))
	// 如果需要,可以添加更多的中间件,再次调用 router.Use
	router.Use(Middleware3, Middleware4, Middleware5)

	_ = http.ListenAndServe(":80", router)
}

你可以在 mux官方文档 上找到更多关于中间件的信息。

英文:

Mux has an official way of doing it
look on this example

// a regular middleware
func Middleware(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		// do stuff before the handlers
		h.ServeHTTP(w, r)
		// do stuff after the hadlers

	})
}

// if you want to pass data into the middleware 
func Middleware2(s string) mux.MiddlewareFunc {
	return func(h http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			// do stuff
			fmt.Println(s)
			h.ServeHTTP(w, r)
		})
	}
}

func main() {
	router := mux.NewRouter()


	router.Use(Middleware)
	//you can apply it to a sub-router too
	subRouter := router.PathPrefix("/sub_router/").Subrouter()
	subRouter.Use(Middleware2("somePrams"))
	// Add more middleware if you need, call router.Use Again
	router.Use(Middleware3, Middleware4, Middleware5)

	_ = http.ListenAndServe(":80", router)
}

the official doc on the mux website

答案3

得分: 13

我不确定为什么@OneOfOne选择将路由器链接到中间件中,我认为这是一个稍微更好的方法:

func main() {
    r.Handle("/", Middleware(http.HandlerFunc(homeHandler)))
    http.Handle("/", r)
}

func Middleware(h http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        h.ServeHTTP(w, r)
    })
}
英文:

I'm not sure why @OneOfOne chose to chain router into the Middleware, I think this is slight better approach:

func main() {
    r.Handle("/",Middleware(http.HandlerFunc(homeHandler)))
    http.Handle("/", r)
}

func Middleware(h http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    h.ServeHTTP(w, r)
})}

答案4

得分: 6

如果你想将中间件链应用于路由器或子路由器的所有路由,你可以使用Gorilla mux的一个分支 https://github.com/bezrukovspb/mux

subRouter := router.PathPrefix("/use-a-b").Subrouter().Use(middlewareA, middlewareB)
subRouter.Path("/hello").HandlerFunc(requestHandlerFunc)

英文:

If you want to apply a middleware chain to all routes of a router or subrouter you can use a fork of Gorilla mux https://github.com/bezrukovspb/mux

subRouter := router.PathPrefix("/use-a-b").Subrouter().Use(middlewareA, middlewareB)
subRouter.Path("/hello").HandlerFunc(requestHandlerFunc)

答案5

得分: 0

你可以考虑使用一个中间件包,比如negroni

英文:

You might consider a middleware package such as negroni.

1: http://negroni.codegangsta.io/ "negroni"

huangapple
  • 本文由 发表于 2014年10月6日 00:05:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/26204485.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定