middleware.go 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. package bugsnag
  2. import (
  3. "net/http"
  4. "strings"
  5. )
  6. type (
  7. beforeFunc func(*Event, *Configuration) error
  8. // MiddlewareStacks keep middleware in the correct order. They are
  9. // called in reverse order, so if you add a new middleware it will
  10. // be called before all existing middleware.
  11. middlewareStack struct {
  12. before []beforeFunc
  13. }
  14. )
  15. // AddMiddleware adds a new middleware to the outside of the existing ones,
  16. // when the middlewareStack is Run it will be run before all middleware that
  17. // have been added before.
  18. func (stack *middlewareStack) OnBeforeNotify(middleware beforeFunc) {
  19. stack.before = append(stack.before, middleware)
  20. }
  21. // Run causes all the middleware to be run. If they all permit it the next callback
  22. // will be called with all the middleware on the stack.
  23. func (stack *middlewareStack) Run(event *Event, config *Configuration, next func() error) error {
  24. // run all the before filters in reverse order
  25. for i := range stack.before {
  26. before := stack.before[len(stack.before)-i-1]
  27. severity := event.Severity
  28. err := stack.runBeforeFilter(before, event, config)
  29. if err != nil {
  30. return err
  31. }
  32. if event.Severity != severity {
  33. event.handledState.SeverityReason = SeverityReasonCallbackSpecified
  34. }
  35. }
  36. return next()
  37. }
  38. func (stack *middlewareStack) runBeforeFilter(f beforeFunc, event *Event, config *Configuration) error {
  39. defer func() {
  40. if err := recover(); err != nil {
  41. config.logf("bugsnag/middleware: unexpected panic: %v", err)
  42. }
  43. }()
  44. return f(event, config)
  45. }
  46. // catchMiddlewarePanic is used to log any panics that happen inside Middleware,
  47. // we wouldn't want to not notify Bugsnag in this case.
  48. func catchMiddlewarePanic(event *Event, config *Configuration, next func() error) {
  49. }
  50. // httpRequestMiddleware is added OnBeforeNotify by default. It takes information
  51. // from an http.Request passed in as rawData, and adds it to the Event. You can
  52. // use this as a template for writing your own Middleware.
  53. func httpRequestMiddleware(event *Event, config *Configuration) error {
  54. for _, datum := range event.RawData {
  55. if request, ok := datum.(*http.Request); ok {
  56. proto := "http://"
  57. if request.TLS != nil {
  58. proto = "https://"
  59. }
  60. event.MetaData.Update(MetaData{
  61. "request": {
  62. "clientIp": request.RemoteAddr,
  63. "httpMethod": request.Method,
  64. "url": proto + request.Host + request.RequestURI,
  65. "params": request.URL.Query(),
  66. "headers": request.Header,
  67. },
  68. })
  69. // Default context to Path
  70. if event.Context == "" {
  71. event.Context = request.URL.Path
  72. }
  73. // Default user.id to IP so that users-affected works.
  74. if event.User == nil {
  75. ip := request.RemoteAddr
  76. if idx := strings.LastIndex(ip, ":"); idx != -1 {
  77. ip = ip[:idx]
  78. }
  79. event.User = &User{Id: ip}
  80. }
  81. }
  82. }
  83. return nil
  84. }