如何在不使用DefaultServeMux的情况下实现HandlerFunc [英] How to implement HandlerFunc without using DefaultServeMux
问题描述
如果我使用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屋!