upaas/internal/handlers/webhook.go

76 lines
1.7 KiB
Go

package handlers
import (
"io"
"net/http"
"github.com/go-chi/chi/v5"
"git.eeqj.de/sneak/upaas/internal/models"
)
// maxWebhookBodySize is the maximum allowed size of a webhook request body (1MB).
const maxWebhookBodySize = 1 << 20
// HandleWebhook handles incoming Gitea webhooks.
func (h *Handlers) HandleWebhook() http.HandlerFunc {
return func(writer http.ResponseWriter, request *http.Request) {
secret := chi.URLParam(request, "secret")
if secret == "" {
http.NotFound(writer, request)
return
}
// Find app by webhook secret
application, findErr := models.FindAppByWebhookSecret(
request.Context(),
h.db,
secret,
)
if findErr != nil {
h.log.Error("failed to find app by webhook secret", "error", findErr)
http.Error(writer, "Internal Server Error", http.StatusInternalServerError)
return
}
if application == nil {
http.NotFound(writer, request)
return
}
// Read request body with size limit to prevent memory exhaustion
body, readErr := io.ReadAll(io.LimitReader(request.Body, maxWebhookBodySize))
if readErr != nil {
h.log.Error("failed to read webhook body", "error", readErr)
http.Error(writer, "Bad Request", http.StatusBadRequest)
return
}
// Get event type from header
eventType := request.Header.Get("X-Gitea-Event")
if eventType == "" {
eventType = "push"
}
// Process webhook
webhookErr := h.webhook.HandleWebhook(
request.Context(),
application,
eventType,
body,
)
if webhookErr != nil {
h.log.Error("failed to process webhook", "error", webhookErr)
http.Error(writer, "Internal Server Error", http.StatusInternalServerError)
return
}
writer.WriteHeader(http.StatusOK)
}
}