如何在不使用DefaultServeMux的情况下实现HandlerFunc [英] How to implement HandlerFunc without using DefaultServeMux

查看:141
本文介绍了如何在不使用DefaultServeMux的情况下实现HandlerFunc的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我使用DefaultServeMux(我通过传递 nil 作为ListenAndServe的第二个参数来指定),那么我可以访问 http .HandleFunc ,你可以在Go的wiki中看到这个例子:

  func handler( w http.ResponseWriter,r * http.Request){
fmt.Fprintf(w,你好,我爱%s!,r.URL.Path [1:])
}

func main(){
http.HandleFunc(/,handler)
http.ListenAndServe(:8080,nil)
}

在我当前的代码中,我无法使用DefaultServeMux,即将自定义处理程序传递给ListenAndServe

  h:=& mypackage.Handler {
数据库:mydb
}
http.ListenAndServe( :8080,h)

所以我没有得到 http .HandleFunc 内置。但是,我必须调整一些授权代码到我的代码库,需要像 http.Han dleFunc 。例如,如果我一直在使用DefaultServeMux,当我点击/ protected路由时,我想要转到 Protected 处理程序,但只有在通过 h.AuthorizationHandlerFunc 类似这样的

  h.AuthorizationHandlerFunc(受保护的)

但是,由于我没有使用DefaultServeMux,不工作,即我无法将 Protected 函数(并将其调用)传递给 AuthorizationHandlerFunc 。这是下面的AuthorizationHandlerFunc的实现。你可以在下面看到 Protected 永远不会被调用。

问题:如何在这种情况下(不使用DefaultServeMux)实现 HandlerFunc
$ b

  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){
//其他的东西发生
log.Println(这永远不会被调用)
下一个(w,r)
}
func(h * Handler)受保护(w http.ResponseWriter,r * http.Request){

log.Println(this b


$ b

更新
ServeHTTP在mypackage.Handler上实现。为什么Protected函数没有被调用,或者对于这个问题,AuthorizationMiddleWare中的相关代码是什么?解析方案

重新实现您的授权中间件作为 http.Handler

  type auth struct { 
DB * sql.DB
UnauthorizedHandler http.Handler
}
$ b $ func NewAuth(db * sql.DB,未授权的http.Handler)* auth {
返回auth {db,未授权}
}

func(a * auth)受保护(h http.Handler)http.Handler {
fn:= func(w http。 ResponseWriter,r * http.Request){
//检查请求是否有效
//如果它无效,请调用你的错误func并确保*返回*提前!
if!valid {
a.UnauthorizedHandler.ServeHTTP(w,r)
return
}
//成功时调用下一个处理函数
h。 ServeHTTP(w,r)
返回
}

返回http.HandlerFunc(fn)
}

func someHandler(w http。 ResponseWriter,r * http.Request){
io.WriteString(w,Hello!\\\

}

func main(){
auth := NewAuth(db,errorHandler)
r:= http.NewServeMux()
//我们有一个http.Handler实现封装了一个http.HandlerFunc
// ...所以我们调用r.Handle在我们的ServeMux上并且输入包装的func
r.Handle(/ protected,auth.Protected(http.HandlerFunc(someHandler)))
//只需一个简单的http.HandlerFunc这里
r.HandleFunc(/ public,someOtherHandler)

log.Fatal(http.ListenAndServe(:8000,r))
}

查看 httpauth lib我用 ServeHTTP 方法写了一个不同的例子。上述和显式创建 ServeHTTP 方法都是有效的方法。


If I were to use the DefaultServeMux (which I designate by passing nil as the second argument to ListenAndServe), then I have access to http.HandleFunc, which you see used below in this example from the Go wiki:

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

In my current code, I am not able to use the DefaultServeMux i.e. I'm passing a custom handler to ListenAndServe

    h := &mypackage.Handler{
        Database: mydb
    }
    http.ListenAndServe(":8080", h)

so I don't get the http.HandleFunc built in. However, I have to adapt some authorization code to my code base that requires something like http.HandleFunc. For example, if I had been using DefaultServeMux, when I hit the "/protected" route, I would want to go to the Protected handler, but only after passing through the h.AuthorizationHandlerFunc like this

   h.AuthorizationHandlerFunc(Protected)

However, since I'm not using DefaultServeMux, it's not working i.e. I'm not able to pass the Protected function (and have it called) to the AuthorizationHandlerFunc. This is the implementation of the AuthorizationHandlerFunc below. You can see below that Protected never gets called.

Question: how do I implement HandlerFunc in this situation (without using DefaultServeMux)?

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

Update ServeHTTP is implemented on mypackage.Handler. Why is the Protected function not getting called, or, for that matter, the relevant code in the AuthorizationMiddleWare?

解决方案

Re-implement your authorization middleware as a 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.

这篇关于如何在不使用DefaultServeMux的情况下实现HandlerFunc的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆