事件回调

HTTP Dispatcher没有Logger这个概念,而是抽象成了事件的概念。当调度器内出现错误时,会生成事件(httpdispatcher.Event),并将事件传递给传入的事件处理器,然后自行选择Logger来记录事件,目前支持404、405、500三种状态的事件。

  1. type Event struct {
  2. Status int // HTTP状态码
  3. Trace []string // 触发事件的trace
  4. Message error // 事件消息文本
  5. ResponseWriter http.ResponseWriter
  6. Request *http.Request
  7. }

示例如下:

  1. package main
  2.  
  3. import (
  4. "github.com/dxvgef/httpdispatcher"
  5. "net/http"
  6. "fmt"
  7. )
  8.  
  9. func main() {
  10. var dispatcher = httpdispatcher.New()
  11. dispatcher.Event.EnableTrace = true // 开启panic错误的trace
  12. dispatcher.Event.ShortCaller = true // trace消息中的源码文件记录短路径
  13. //传入一个事件处理函数,如果不传入此函数,则不会抛出任何事件
  14. dispatcher.Event.Handler = func(event *httpdispatcher.Event) {
  15. event.ResponseWriter.WriteHeader(event.Status)
  16. event.ResponseWriter.Write([]byte(http.StatusText(event.Status)))
  17.  
  18. // 打印事件消息
  19. fmt.Println(event.Message.Error())
  20.  
  21. // 打印trace,仅在500事件的时候event.Trace才有值
  22. if event.Status == 500 {
  23. var trace string
  24. trace += "\nTrace:"
  25. for k := range event.Trace {
  26. trace += "\n" + event.Trace[k]
  27. }
  28. fmt.Println(trace)
  29. }
  30. }
  31.  
  32. svr := &http.Server{
  33. Addr: ":8080",
  34. Handler: dispatcher,
  35. }
  36. if err := svr.ListenAndServe(); err != nil {
  37. log.Fatal(err.Error())
  38. }
  39. }

注意,上面的代码并没有注册任何路由,在访问8080端口的任何路径都会触发404事件。

在路由处理器函数里,可以通过以下三种方法来触发500事件:

1. 运行时错误触发500事件

  1. dispatcher.Router.GET("/", func(ctx *httpdispatcher.Context) error {
  2. var s []int
  3. //此处有个下标越界的运行时错误
  4. println("通过运行时错误触发500事件", s[2])
  5.  
  6. return nil
  7. })

2. 主动抛出panic触发500事件

  1. dispatcher.Router.GET("/", func(ctx *httpdispatcher.Context) error {
  2. panic("主动抛出panic触发500事件")
  3. return nil
  4. })

3. 路由处理器函数返回参数值不为nil,触发500事件

  1. dispatcher.Router.GET("/", func(ctx *httpdispatcher.Context) error {
  2. return errors.New("通过返回非nil触发500事件")
  3. })

直接使用return errors.New("…")触发的500事件,trace中的信息太多,可以使用Context.Event方法来精准定位到触发500事件的源码文件及行号,示例如下:

  1. dispatcher.Router.GET("/", func(ctx *httpdispatcher.Context) error {
  2. return ctx.Event(errors.New("通过Context.Return返回非nil触发500事件"))
  3. })