Go网络编程-Middleware (Advanced)
跳到导航
跳到搜索
这个例子将展示如何在Go中创建一个更高级的中间件版本。
中间件本身简单地接受一个http.HandlerFunc作为参数之一,将其包装并返回一个新的http.HandlerFunc供服务器调用。
在这里我们定义了一个新的类型Middleware,这使得最终更容易地将多个中间件链接在一起。这个想法受到了Mat Ryers关于构建API的演讲的启发。
这段代码详细解释了如何创建一个新的中间件。在下面的完整示例中,我们通过一些样板代码简化了这个版本。
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)
}
$ 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