mirror of https://github.com/matrix-org/go-neb.git
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
66 lines
2.1 KiB
package handlers
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/matrix-org/go-neb/clients"
|
|
"github.com/matrix-org/go-neb/database"
|
|
"github.com/matrix-org/go-neb/metrics"
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// Webhook represents an HTTP handler capable of accepting webhook requests on behalf of services.
|
|
type Webhook struct {
|
|
db *database.ServiceDB
|
|
clients *clients.Clients
|
|
}
|
|
|
|
// NewWebhook returns a new webhook HTTP handler
|
|
func NewWebhook(db *database.ServiceDB, cli *clients.Clients) *Webhook {
|
|
return &Webhook{db, cli}
|
|
}
|
|
|
|
// Handle an incoming webhook HTTP request.
|
|
//
|
|
// The webhook MUST have a known base64 encoded service ID as the last path segment
|
|
// in order for this request to be passed to the correct service, or else this will return
|
|
// HTTP 400. If the base64 encoded service ID is unknown, this will return HTTP 404.
|
|
// Beyond this, the exact response is determined by the specific Service implementation.
|
|
func (wh *Webhook) Handle(w http.ResponseWriter, req *http.Request) {
|
|
log.WithField("path", req.URL.Path).Print("Incoming webhook request")
|
|
segments := strings.Split(req.URL.Path, "/")
|
|
// last path segment is the service ID which we will pass the incoming request to,
|
|
// but we've base64d it.
|
|
base64srvID := segments[len(segments)-1]
|
|
bytesSrvID, err := base64.RawURLEncoding.DecodeString(base64srvID)
|
|
if err != nil {
|
|
log.WithError(err).WithField("base64_service_id", base64srvID).Print(
|
|
"Not a b64 encoded string",
|
|
)
|
|
w.WriteHeader(400)
|
|
return
|
|
}
|
|
srvID := string(bytesSrvID)
|
|
|
|
service, err := wh.db.LoadService(srvID)
|
|
if err != nil {
|
|
log.WithError(err).WithField("service_id", srvID).Print("Failed to load service")
|
|
w.WriteHeader(404)
|
|
return
|
|
}
|
|
cli, err := wh.clients.Client(service.ServiceUserID())
|
|
if err != nil {
|
|
log.WithError(err).WithField("user_id", service.ServiceUserID()).Print(
|
|
"Failed to retrieve matrix client instance")
|
|
w.WriteHeader(500)
|
|
return
|
|
}
|
|
log.WithFields(log.Fields{
|
|
"service_id": service.ServiceID(),
|
|
"service_type": service.ServiceType(),
|
|
}).Print("Incoming webhook for service")
|
|
metrics.IncrementWebhook(service.ServiceType())
|
|
service.OnReceiveWebhook(w, req, cli)
|
|
}
|