You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

66 lines
2.1 KiB

  1. package handlers
  2. import (
  3. "encoding/base64"
  4. "net/http"
  5. "strings"
  6. "github.com/matrix-org/go-neb/clients"
  7. "github.com/matrix-org/go-neb/database"
  8. "github.com/matrix-org/go-neb/metrics"
  9. log "github.com/sirupsen/logrus"
  10. )
  11. // Webhook represents an HTTP handler capable of accepting webhook requests on behalf of services.
  12. type Webhook struct {
  13. db *database.ServiceDB
  14. clients *clients.Clients
  15. }
  16. // NewWebhook returns a new webhook HTTP handler
  17. func NewWebhook(db *database.ServiceDB, cli *clients.Clients) *Webhook {
  18. return &Webhook{db, cli}
  19. }
  20. // Handle an incoming webhook HTTP request.
  21. //
  22. // The webhook MUST have a known base64 encoded service ID as the last path segment
  23. // in order for this request to be passed to the correct service, or else this will return
  24. // HTTP 400. If the base64 encoded service ID is unknown, this will return HTTP 404.
  25. // Beyond this, the exact response is determined by the specific Service implementation.
  26. func (wh *Webhook) Handle(w http.ResponseWriter, req *http.Request) {
  27. log.WithField("path", req.URL.Path).Print("Incoming webhook request")
  28. segments := strings.Split(req.URL.Path, "/")
  29. // last path segment is the service ID which we will pass the incoming request to,
  30. // but we've base64d it.
  31. base64srvID := segments[len(segments)-1]
  32. bytesSrvID, err := base64.RawURLEncoding.DecodeString(base64srvID)
  33. if err != nil {
  34. log.WithError(err).WithField("base64_service_id", base64srvID).Print(
  35. "Not a b64 encoded string",
  36. )
  37. w.WriteHeader(400)
  38. return
  39. }
  40. srvID := string(bytesSrvID)
  41. service, err := wh.db.LoadService(srvID)
  42. if err != nil {
  43. log.WithError(err).WithField("service_id", srvID).Print("Failed to load service")
  44. w.WriteHeader(404)
  45. return
  46. }
  47. cli, err := wh.clients.Client(service.ServiceUserID())
  48. if err != nil {
  49. log.WithError(err).WithField("user_id", service.ServiceUserID()).Print(
  50. "Failed to retrieve matrix client instance")
  51. w.WriteHeader(500)
  52. return
  53. }
  54. log.WithFields(log.Fields{
  55. "service_id": service.ServiceID(),
  56. "service_type": service.ServiceType(),
  57. }).Print("Incoming webhook for service")
  58. metrics.IncrementWebhook(service.ServiceType())
  59. service.OnReceiveWebhook(w, req, cli)
  60. }