Middleware (Advanced)

这个例子将展示如何在GO中创建更高级的中间件。一个中间件只需要一个http.HandlerFunc 作为它的一个参数,装饰它并把它作为一个新的 http.HandlerFunc 给服务器调用.

在这里,我们定义一个新的类型 Middleware, 它可以更容易的链接多个中间件。这个想法灵感来自于Mat Ryer 谈论如果建立APIs. 你可以从 这里查看更详细的内容.

这个片段详细展示了如何创建一个新的中间件。此处下面是完整的例子,这里我们减少了一些样板代码.

  1. func createNewMiddleware() Middleware {
  2. // Create a new Middleware
  3. middleware := func(next http.HandlerFunc) http.HandlerFunc {
  4. // Define the http.HandlerFunc which is called by the server eventually
  5. handler := func(w http.ResponseWriter, r *http.Request) {
  6. // ... do middleware things
  7. // Call the next middleware/handler in chain
  8. next(w, r)
  9. }
  10. // Return newly created handler
  11. return handler
  12. }
  13. // Return newly created middleware
  14. return middleware
  15. }


下面是完整的例子:

  1. // advanced-middleware.go
  2. package main
  3. import (
  4. "fmt"
  5. "log"
  6. "net/http"
  7. "time"
  8. )
  9. type Middleware func(http.HandlerFunc) http.HandlerFunc
  10. // Logging logs all requests with its path and the time it took to process
  11. func Logging() Middleware {
  12. // Create a new Middleware
  13. return func(f http.HandlerFunc) http.HandlerFunc {
  14. // Define the http.HandlerFunc
  15. return func(w http.ResponseWriter, r *http.Request) {
  16. // Do middleware things
  17. start := time.Now()
  18. defer func() { log.Println(r.URL.Path, time.Since(start)) }()
  19. // Call the next middleware/handler in chain
  20. f(w, r)
  21. }
  22. }
  23. }
  24. // Method ensures that url can only be requested with a specific method, else returns a 400 Bad Request
  25. func Method(m string) Middleware {
  26. // Create a new Middleware
  27. return func(f http.HandlerFunc) http.HandlerFunc {
  28. // Define the http.HandlerFunc
  29. return func(w http.ResponseWriter, r *http.Request) {
  30. // Do middleware things
  31. if r.Method != m {
  32. http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
  33. return
  34. }
  35. // Call the next middleware/handler in chain
  36. f(w, r)
  37. }
  38. }
  39. }
  40. // Chain applies middlewares to a http.HandlerFunc
  41. func Chain(f http.HandlerFunc, middlewares ...Middleware) http.HandlerFunc {
  42. for _, m := range middlewares {
  43. f = m(f)
  44. }
  45. return f
  46. }
  47. func Hello(w http.ResponseWriter, r *http.Request) {
  48. fmt.Fprintln(w, "hello world")
  49. }
  50. func main() {
  51. http.HandleFunc("/", Chain(Hello, Method("GET"), Logging()))
  52. http.ListenAndServe(":8080", nil)
  53. }
  1. $ go run advanced-middleware.go
  2. 2017/02/11 00:34:53 / 0s
  3. $ curl -s http://localhost:8080/
  4. hello world
  5. $ curl -s -XPOST http://localhost:8080/
  6. Bad Request