如果我要使用DefaultServeMux(我将其指定nil为ListenAndServe的第二个参数来指定),那么我可以访问http.HandleFunc,您可以在Go Wiki的以下示例中看到该:
nil
http.HandleFunc
func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:]) } func main() { http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil) }
在当前代码中,我无法使用DefaultServeMux,即我将自定义处理程序传递给ListenAndServe
h := &mypackage.Handler{ Database: mydb } http.ListenAndServe(":8080", h)
因此,我没有http.HandleFunc内置的代码。但是,我必须将一些授权代码修改为需要类似的授权代码http.HandleFunc。例如,如果我一直在使用DefaultServeMux,则当我点击"/protected"路线时,我想转到Protected处理程序,但仅在经过h.AuthorizationHandlerFunc这样的处理之后
"/protected"
Protected
h.AuthorizationHandlerFunc
h.AuthorizationHandlerFunc(Protected)
但是,由于我没有使用DefaultServeMux,因此无法正常工作,即无法将Protected函数(并调用它)传递给AuthorizationHandlerFunc。这是下面的AuthorizationHandlerFunc的实现。您可以在下面看到Protected永不被调用。
AuthorizationHandlerFunc
问题:HandlerFunc在这种情况下(不使用DefaultServeMux)如何实现?
HandlerFunc
func (h *Handler) AuthorizationHandlerFunc(next http.HandlerFunc) http.Handler{ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){ h.AuthorizationMiddleWare(w, r, next) }) } func (h *Handler) AuthorizationMiddleWare(w http.ResponseWriter, r *http.Request, next http.HandlerFunc){ //other stuff happens log.Println("this is never getting called") next(w,r) } func (h *Handler)Protected(w http.ResponseWriter, r *http.Request){ log.Println("this is never getting called") }
更新 ServeHTTP在mypackage.Handler上实现。为什么未调用Protected函数,或者为什么没有在AuthorizationMiddleWare中调用相关代码?
将您的授权中间件重新实现为http.Handler:
http.Handler
type auth struct { DB *sql.DB UnauthorizedHandler http.Handler } func NewAuth(db *sql.DB, unauthorized http.Handler) *auth { return auth{db, unauthorized} } func (a *auth) Protected(h http.Handler) http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { // Check whether the request is valid // If it's invalid, call your error func and make sure to *return* early! if !valid { a.UnauthorizedHandler.ServeHTTP(w, r) return } // Call the next handler on success h.ServeHTTP(w, r) return } return http.HandlerFunc(fn) } func someHandler(w http.ResponseWriter, r *http.Request) { io.WriteString(w, "Hello!\n") } func main() { auth := NewAuth(db, errorHandler) r := http.NewServeMux() // We have a http.Handler implementation that wraps a http.HandlerFunc // ... so we call r.Handle on our ServeMux and type-cast the wrapped func r.Handle("/protected", auth.Protected(http.HandlerFunc(someHandler))) // Just a simple http.HandlerFunc here r.HandleFunc("/public", someOtherHandler) log.Fatal(http.ListenAndServe(":8000", r)) }
Take a look at the httpauth lib I wrote for a different example with a ServeHTTP method. Both the above and explicitly creating a ServeHTTP method on your type are valid approaches.
ServeHTTP