Middleware-中间件(高级)
Middleware (高级)
本示例将展示如何在Go中创建更高级版本的中间件。
中间件本身只接受 http.HandlerFunc
作为其参数之一,包装它并返回新的 http.HandlerFunc
的服务调用。
在这里,我们定义了一种新型 Middleware
,它最终使将多个中间件链接在一起变得更容易。这个想法受到 Mat Ryers’ 关于构建API的讨论的启发。你可以在 here找到更详细的解释,包括演讲。
这个片段详细解释了如何创建新的中间件。在下面的完整示例中,我们通过一些样板代码减少了这个版本。
func createNewMiddleware() Middleware {
// Create a new Middleware
middleware := func(next http.HandlerFunc) http.HandlerFunc {
// Define the http.HandlerFunc which is called by the server eventually
handler := func(w http.ResponseWriter, r *http.Request) {
// ... do middleware things
// Call the next middleware/handler in chain
next(w, r)
}
// Return newly created handler
return handler
}
// Return newly created middleware
return middleware
}
完整例子
// advanced-middleware.go
package main
import (
"fmt"
"log"
"net/http"
"time"
)
type Middleware func(http.HandlerFunc) http.HandlerFunc
// Logging logs all requests with its path and the time it took to process
func Logging() Middleware {
// Create a new Middleware
return func(f http.HandlerFunc) http.HandlerFunc {
// Define the http.HandlerFunc
return func(w http.ResponseWriter, r *http.Request) {
// Do middleware things
start := time.Now()
defer func() { log.Println(r.URL.Path, time.Since(start)) }()
// Call the next middleware/handler in chain
f(w, r)
}
}
}
// Method ensures that url can only be requested with a specific method, else returns a 400 Bad Request
func Method(m string) Middleware {
// Create a new Middleware
return func(f http.HandlerFunc) http.HandlerFunc {
// Define the http.HandlerFunc
return func(w http.ResponseWriter, r *http.Request) {
// Do middleware things
if r.Method != m {
http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
return
}
// Call the next middleware/handler in chain
f(w, r)
}
}
}
// Chain applies middlewares to a http.HandlerFunc
func Chain(f http.HandlerFunc, middlewares ...Middleware) http.HandlerFunc {
for _, m := range middlewares {
f = m(f)
}
return f
}
func Hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "hello world")
}
func main() {
http.HandleFunc("/", Chain(Hello, Method("GET"), Logging()))
http.ListenAndServe(":8080", nil)
}
run
$ go run advanced-middleware.go
2017/02/11 00:34:53 / 0s
$ curl -s http://localhost:8080/
hello world
$ curl -s -XPOST http://localhost:8080/
Bad Request