request_extractor.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. package bugsnag
  2. import (
  3. "context"
  4. "net/http"
  5. "strings"
  6. )
  7. const requestContextKey requestKey = iota
  8. type requestKey int
  9. // AttachRequestData returns a child of the given context with the request
  10. // object attached for later extraction by the notifier in order to
  11. // automatically record request data
  12. func AttachRequestData(ctx context.Context, r *http.Request) context.Context {
  13. return context.WithValue(ctx, requestContextKey, r)
  14. }
  15. // extractRequestInfo looks for the request object that the notifier
  16. // automatically attaches to the context when using any of the supported
  17. // frameworks or bugsnag.HandlerFunc or bugsnag.Handler, and returns sub-object
  18. // supported by the notify API.
  19. func extractRequestInfo(ctx context.Context) (*RequestJSON, *http.Request) {
  20. if req := getRequestIfPresent(ctx); req != nil {
  21. return extractRequestInfoFromReq(req), req
  22. }
  23. return nil, nil
  24. }
  25. // extractRequestInfoFromReq extracts the request information the notify API
  26. // understands from the given HTTP request. Returns the sub-object supported by
  27. // the notify API.
  28. func extractRequestInfoFromReq(req *http.Request) *RequestJSON {
  29. proto := "http://"
  30. if req.TLS != nil {
  31. proto = "https://"
  32. }
  33. return &RequestJSON{
  34. ClientIP: req.RemoteAddr,
  35. HTTPMethod: req.Method,
  36. URL: proto + req.Host + req.RequestURI,
  37. Referer: req.Referer(),
  38. Headers: parseRequestHeaders(req.Header),
  39. }
  40. }
  41. func parseRequestHeaders(header map[string][]string) map[string]string {
  42. headers := make(map[string]string)
  43. for k, v := range header {
  44. // Headers can have multiple values, in which case we report them as csv
  45. if contains(Config.ParamsFilters, k) {
  46. headers[k] = "[FILTERED]"
  47. } else {
  48. headers[k] = strings.Join(v, ",")
  49. }
  50. }
  51. return headers
  52. }
  53. func contains(slice []string, e string) bool {
  54. for _, s := range slice {
  55. if strings.ToLower(s) == strings.ToLower(e) {
  56. return true
  57. }
  58. }
  59. return false
  60. }
  61. func getRequestIfPresent(ctx context.Context) *http.Request {
  62. if ctx == nil {
  63. return nil
  64. }
  65. val := ctx.Value(requestContextKey)
  66. if val == nil {
  67. return nil
  68. }
  69. return val.(*http.Request)
  70. }