我想使用此处指定的处理程序来记录所有内容。
这就是我所拥有的:
r := mux.NewRouter()
s := r.PathPrefix("/api/v1").Subrouter()
s.HandleFunc("/abc", handler.GetAbc).Methods("GET")
s.HandleFunc("/xyz", handler.GetXyz).Methods("GET")
Run Code Online (Sandbox Code Playgroud)
我想使用日志中间件,但我不想在每一行中重复它,正如它们在 github 中显示的那样:
r.Handle("/admin", handlers.LoggingHandler(os.Stdout, http.HandlerFunc(ShowAdminDashboard)))
r.HandleFunc("/", ShowIndex)
Run Code Online (Sandbox Code Playgroud)
有没有办法只将通用日志中间件传递给r,所有通过r路由器的东西都会先通过中间件?
使用中间件:
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Do stuff here
log.Println(r.RequestURI)
// Call the next handler, which can be another middleware in the chain, or the final handler.
next.ServeHTTP(w, r)
})
}
r.Use(loggingMiddleware)
Run Code Online (Sandbox Code Playgroud)
这是文档:https : //github.com/gorilla/mux#middleware
我用中间件函数包装了 LoggingHandler
func loggingMiddleware(next http.Handler) http.Handler {
return handlers.LoggingHandler(os.Stdout, next)
}
r.Use(loggingMiddleware)
Run Code Online (Sandbox Code Playgroud)
这是我采取的方法,这对我来说效果最好。
type Route struct {
Name string
Method string
Pattern string
Secure bool
HandlerFunc http.HandlerFunc
}
type Routes []Route
var routes = Routes{
Route{
Name: "Docs",
Method: "GET",
Pattern: "/v2/docs",
HandlerFunc: Docs,
},
Route{
Name: "GetUserByName",
Method: "GET",
Pattern: "/v2/user/{username}",
HandlerFunc: user.GetUserByName,
Secure: true,
},
}
func NewRouter() *mux.Router {
router := mux.NewRouter().StrictSlash(true)
router.NotFoundHandler = http.HandlerFunc(notFound)
router.MethodNotAllowedHandler = http.HandlerFunc(notAllowed)
for _, route := range routes {
var handler http.Handler
if route.Secure {
handler = AuthMiddleware(route.HandlerFunc)
} else {
handler = route.HandlerFunc
}
handler = Logger(os.Stderr, handler)
router.
Methods(route.Method).
Path(route.Pattern).
Name(route.Name).
Handler(handler)
}
return router
}
func ApplicationRecovery(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if err := recover(); err != nil {
fmt.Fprintln(os.Stderr, "Recovered from application error occurred")
_, _ = fmt.Fprintln(os.Stderr, err)
w.WriteHeader(http.StatusInternalServerError)
}))
}
}()
next.ServeHTTP(w, r)
})
}
func Middleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Add("Content-Type", "application/json")
next.ServeHTTP(w, r)
})
}
func AuthMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
//TODO: Add authentication
log.Println("Authentication required")
next.ServeHTTP(w, r)
})
}
func Logger(inner http.Handler, name string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
log.Printf(
"%s %s %s %s",
r.Method,
r.RequestURI,
name,
time.Since(start),
)
inner.ServeHTTP(w, r)
})
}
func notFound(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
}
func notAllowed(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusMethodNotAllowed)
}
func main() {
srv := http.Server{
Addr: "0.0.0.0:8080",
Handler: ApplicationRecovery(Middleware(NewRouter())),
ReadTimeout: 15 * time.Second,
WriteTimeout: 15 * time.Second,
}
log.Fatal(srv.ListenAndServe())
}
Run Code Online (Sandbox Code Playgroud)
这样我就可以覆盖我的基础:
2020/06/23 22:28:48 Server started
2020/06/23 22:28:51 Authentication required
2020/06/23 22:28:51 Begin x-api-key validation
2020/06/23 22:28:51 x-api-key matched user: 1
2020/06/23 22:28:51 User 1 successfully accessed secure resourecs
::1 - - [23/Jun/2020:22:28:51 +0100] "DELETE /v2/user/john?permanent=true HTTP/1.1" 403 85
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2313 次 |
| 最近记录: |