doubipeng1336 2015-09-01 11:44
浏览 26
已采纳

如何在不使用DefaultServeMux的情况下实现HandlerFunc

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?

  • 写回答

1条回答 默认 最新

  • duanpaotian2348 2015-09-01 12:23
    关注

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

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 测距传感器数据手册i2c
  • ¥15 RPA正常跑,cmd输入cookies跑不出来
  • ¥15 求帮我调试一下freefem代码
  • ¥15 matlab代码解决,怎么运行
  • ¥15 R语言Rstudio突然无法启动
  • ¥15 关于#matlab#的问题:提取2个图像的变量作为另外一个图像像元的移动量,计算新的位置创建新的图像并提取第二个图像的变量到新的图像
  • ¥15 改算法,照着压缩包里边,参考其他代码封装的格式 写到main函数里
  • ¥15 用windows做服务的同志有吗
  • ¥60 求一个简单的网页(标签-安全|关键词-上传)
  • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法