如何将多个处理程序分配给同一个 uri?

How to assign multiple handlers to the same uri in go?

当请求中出现“/”模式时,我有两个任务需要完成,这两个任务都需要使用 http 处理程序。

他们是:

http.Handle("/", http.FileServer(http.Dir("dtfw-tool/build/")))
http.HandleFunc("/", index)

索引处理程序检查正确的身份验证以访问网页,它上面的处理程序提供一个目录(将来我会把它放到只在满足身份验证要求的情况下才提供目录的地方)。

是否可以为同一个模式设置两个处理程序(目前出错)?如果没有,是否有任何其他方法来检查身份验证并使用单个处理程序提供目录?

创建一个中间件来验证用户和 return main Handle 的处理程序,它将包装您的最终处理程序

package main

import (
    "log"
    "net/http"
)

func main() {
    finalHandler := http.HandlerFunc(final)
    http.Handle("/", authentication(finalHandler))
    http.ListenAndServe(":3000", nil)
}

func authentication(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        log.Println("Executing authentication")
        next.ServeHTTP(w, r) //`next.ServeHTTP(w, r)` will forward the request and response to next handler.
    })
}

func final(w http.ResponseWriter, r *http.Request) {
    log.Println("Executing finalHandler")
    w.Write([]byte("User authenticated"))
}

在Golang中HanlderFunc用于return hanlder,它将成为一个中间件来包装主要功能:

// The HandlerFunc type is an adapter to allow the use of
// ordinary functions as HTTP handlers. If f is a function
// with the appropriate signature, HandlerFunc(f) is a
// Handler that calls f.
type HandlerFunc func(ResponseWriter, *Request)

server.go

的源代码中也有定义

Playground Example

我将不得不收回我之前接受的答案,因为这更接近我想要的(必须导入 github.com/abbot/go-http-auth):

package main

import (
    "fmt"
    "net/http"
    auth "github.com/abbot/go-http-auth"
)

func Secret(user, realm string) string {
    if user == "john" {
        // password is "hello"
        return "$dlPL2MqE$oQmn16q49SqdmhenQuNgs1"
    }
    return ""
}

func main() {
    fmt.Println("-----> Starting HTTP server...")

authenticator := auth.NewBasicAuthenticator("secret.com", Secret)
http.HandleFunc("/", authenticator.Wrap(func(res http.ResponseWriter, req *auth.AuthenticatedRequest) {
    http.FileServer(http.Dir(".")).ServeHTTP(res, &req.Request)
}))

http.ListenAndServe(":5042", nil)
}

这种方法更容易理解也更直观(至少对我而言)。