原始请求转换成context.Handler

1.面向中间件 negroni-like

目录结构

主目录negroniLike

  1. —— main.go

代码示例

main.go

  1. package main
  2. import (
  3. "net/http"
  4. "github.com/kataras/iris"
  5. )
  6. func main() {
  7. app := iris.New()
  8. //FromStd将原生http.Handler,http.HandlerFunc和func(w,r,next)转换为context.Handler
  9. irisMiddleware := iris.FromStd(negronilikeTestMiddleware)
  10. app.Use(irisMiddleware)
  11. // 请求 GET: http://localhost:8080/
  12. app.Get("/", func(ctx iris.Context) {
  13. ctx.HTML("<h1> Home </h1>")
  14. //这会打印错误
  15. //这个路由的处理程序永远不会被执行,因为中间件的标准没有通过
  16. })
  17. // 请求 GET: http://localhost:8080/ok
  18. app.Get("/ok", func(ctx iris.Context) {
  19. ctx.Writef("Hello world!")
  20. // 这将打印"OK. Hello world!"
  21. })
  22. // http://localhost:8080
  23. // http://localhost:8080/ok
  24. app.Run(iris.Addr(":8080"))
  25. }
  26. func negronilikeTestMiddleware(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
  27. if r.URL.Path == "/ok" && r.Method == "GET" {
  28. w.Write([]byte("OK. "))
  29. next(w, r) // 中间件
  30. return
  31. }
  32. //否则打印错误
  33. w.WriteHeader(iris.StatusBadRequest)
  34. w.Write([]byte("Bad request"))
  35. }
  36. //如果要使用自定义上下文转换自定义处理程序,请查看routing/custom-context
  37. //一个context.Handler

negronigo实现中间件的一种使用很广泛的模式

2.面向net/Http

目录结构

主目录nethttp

  1. —— main.go

代码示例

main.go

  1. package main
  2. import (
  3. "net/http"
  4. "github.com/kataras/iris"
  5. )
  6. func main() {
  7. app := iris.New()
  8. //FromStd将原生http.Handler,http.HandlerFunc和func(w,r,next)转换为context.Handler
  9. irisMiddleware := iris.FromStd(nativeTestMiddleware)
  10. app.Use(irisMiddleware)
  11. // 请求 GET: http://localhost:8080/
  12. app.Get("/", func(ctx iris.Context) {
  13. ctx.HTML("Home")
  14. })
  15. // 请求 GET: http://localhost:8080/ok
  16. app.Get("/ok", func(ctx iris.Context) {
  17. ctx.HTML("<b>Hello world!</b>")
  18. })
  19. // http://localhost:8080
  20. // http://localhost:8080/ok
  21. app.Run(iris.Addr(":8080"))
  22. }
  23. func nativeTestMiddleware(w http.ResponseWriter, r *http.Request) {
  24. println("Request path: " + r.URL.Path)
  25. }
  26. //如果要使用自定义上下文转换自定义处理程序,请查看routing/custom-context
  27. //一个context.Handler。

直接把原生的net/http满足请求接口的函数转化成中间件

3.错误中间件(raven)客户端 https://sentry.io/welcome/

1.修饰路由类型

目录结构

主目录realUsecaseRaven

  1. —— main.go

代码示例

main.go

  1. package main
  2. import (
  3. "errors"
  4. "fmt"
  5. "net/http"
  6. "runtime/debug"
  7. "github.com/kataras/iris"
  8. "github.com/getsentry/raven-go"
  9. )
  10. // https://docs.sentry.io/clients/go/integrations/http/
  11. func init() {
  12. raven.SetDSN("https://<key>:<secret>@sentry.io/<project>")
  13. }
  14. func main() {
  15. app := iris.New()
  16. app.Get("/", func(ctx iris.Context) {
  17. ctx.Writef("Hi")
  18. })
  19. // WrapRouter的示例已在此处:
  20. // https://github.com/kataras/iris/blob/master/_examples/routing/custom-wrapper/main.go#L53
  21. app.WrapRouter(func(w http.ResponseWriter, r *http.Request, irisRouter http.HandlerFunc) {
  22. //完全相同的源代码:
  23. // https://github.com/getsentry/raven-go/blob/379f8d0a68ca237cf8893a1cdfd4f574125e2c51/http.go#L70
  24. defer func() {
  25. if rval := recover(); rval != nil {
  26. debug.PrintStack()
  27. rvalStr := fmt.Sprint(rval)
  28. packet := raven.NewPacket(rvalStr, raven.NewException(errors.New(rvalStr), raven.NewStacktrace(2, 3, nil)), raven.NewHttp(r))
  29. raven.Capture(packet, nil)
  30. w.WriteHeader(http.StatusInternalServerError)
  31. }
  32. }()
  33. irisRouter(w, r)
  34. })
  35. app.Run(iris.Addr(":8080"))
  36. }

2.直接中间件类型

目录结构

主目录writingMiddleware

  1. —— main.go

代码示例

main.go

  1. package main
  2. import (
  3. "errors"
  4. "fmt"
  5. "runtime/debug"
  6. "github.com/kataras/iris"
  7. "github.com/getsentry/raven-go"
  8. )
  9. //raven实现了Sentry错误日志记录服务的客户端。
  10. //在此示例中,您将看到如何转换任何net/http中间件
  11. //具有`(HandlerFunc)HandlerFunc`的形式。
  12. //如果`raven.RecoveryHandler`的形式是
  13. //`(http.HandlerFunc)`或`(http.HandlerFunc,下一个http.HandlerFunc)`
  14. //你可以使用`irisMiddleware:= iris.FromStd(nativeHandler)`
  15. //但它没有,但是你已经知道Iris可以直接使用net/http
  16. //因为`ctx.ResponseWriter()`和`ctx.Request()`是原来的
  17. // http.ResponseWriter和* http.Request。
  18. //(这个是一个很大的优势,因此你可以永远使用Iris :))。
  19. //本机中间件的源代码根本不会改变。
  20. // https://github.com/getsentry/raven-go/blob/379f8d0a68ca237cf8893a1cdfd4f574125e2c51/http.go#L70
  21. //唯一的补充是第18行和第39行(而不是handler(w,r))
  22. //你有一个新的Iris中间件准备使用!
  23. func irisRavenMiddleware(ctx iris.Context) {
  24. w, r := ctx.ResponseWriter(), ctx.Request()
  25. defer func() {
  26. if rval := recover(); rval != nil {
  27. debug.PrintStack()
  28. rvalStr := fmt.Sprint(rval)
  29. packet := raven.NewPacket(rvalStr, raven.NewException(errors.New(rvalStr), raven.NewStacktrace(2, 3, nil)), raven.NewHttp(r))
  30. raven.Capture(packet, nil)
  31. w.WriteHeader(iris.StatusInternalServerError)
  32. }
  33. }()
  34. ctx.Next()
  35. }
  36. // https://docs.sentry.io/clients/go/integrations/http/
  37. func init() {
  38. raven.SetDSN("https://<key>:<secret>@sentry.io/<project>")
  39. }
  40. func main() {
  41. app := iris.New()
  42. app.Use(irisRavenMiddleware)
  43. app.Get("/", func(ctx iris.Context) {
  44. ctx.Writef("Hi")
  45. })
  46. app.Run(iris.Addr(":8080"))
  47. }

提示

  • 主要介绍如何将原始请求转换成context.Handler
  • Negroni是面向web中间件的一种惯用方法.它是微小的,非侵入性的,并且鼓励使用net/http处理器
  • 错误中间件(raven)客户端为我们提供了一个非常清晰的报表,展示我们的响应并提高质量.这是完整的堆栈跟踪.这是一个非常强大的东西