Log every webhook request, not just dispatch failures
Some checks failed
CI / test (push) Has been cancelled
Some checks failed
CI / test (push) Has been cancelled
The handler was silent on success, unauthorized signatures, and unhandled events, making it impossible to tell from server logs alone whether a delivery even arrived. Now every request logs its event type and resulting status code. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
e433aa3538
commit
e95794680b
1 changed files with 28 additions and 20 deletions
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
@ -30,50 +31,57 @@ func NewHandler(secret string, dispatcher Dispatcher) *Handler {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.Method != http.MethodPost {
|
event := firstHeader(r, "X-Forgejo-Event", "X-Gitea-Event")
|
||||||
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
|
status, err := h.handle(w, r, event)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("yaju-keisatsu: %s event -> %d: %v", event, status, err)
|
||||||
|
} else {
|
||||||
|
log.Printf("yaju-keisatsu: %s event -> %d", event, status)
|
||||||
|
}
|
||||||
|
if status != http.StatusNoContent {
|
||||||
|
http.Error(w, http.StatusText(status), status)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
w.WriteHeader(status)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Handler) handle(w http.ResponseWriter, r *http.Request, event string) (int, error) {
|
||||||
|
if r.Method != http.MethodPost {
|
||||||
|
return http.StatusMethodNotAllowed, nil
|
||||||
|
}
|
||||||
|
|
||||||
body, err := io.ReadAll(io.LimitReader(r.Body, 10<<20)) // 10MiB cap
|
body, err := io.ReadAll(io.LimitReader(r.Body, 10<<20)) // 10MiB cap
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "read body", http.StatusBadRequest)
|
return http.StatusBadRequest, fmt.Errorf("read body: %w", err)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !h.validSignature(r, body) {
|
if !h.validSignature(r, body) {
|
||||||
http.Error(w, "invalid signature", http.StatusUnauthorized)
|
return http.StatusUnauthorized, fmt.Errorf("invalid signature")
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
event := firstHeader(r, "X-Forgejo-Event", "X-Gitea-Event")
|
|
||||||
var dispatchErr error
|
|
||||||
switch event {
|
switch event {
|
||||||
case "issue_comment":
|
case "issue_comment":
|
||||||
var p forgejo.IssueCommentPayload
|
var p forgejo.IssueCommentPayload
|
||||||
if err := json.Unmarshal(body, &p); err != nil {
|
if err := json.Unmarshal(body, &p); err != nil {
|
||||||
http.Error(w, "decode payload", http.StatusBadRequest)
|
return http.StatusBadRequest, fmt.Errorf("decode payload: %w", err)
|
||||||
return
|
}
|
||||||
|
if err := h.dispatcher.HandleIssueComment(p); err != nil {
|
||||||
|
return http.StatusInternalServerError, err
|
||||||
}
|
}
|
||||||
dispatchErr = h.dispatcher.HandleIssueComment(p)
|
|
||||||
case "push":
|
case "push":
|
||||||
var p forgejo.PushPayload
|
var p forgejo.PushPayload
|
||||||
if err := json.Unmarshal(body, &p); err != nil {
|
if err := json.Unmarshal(body, &p); err != nil {
|
||||||
http.Error(w, "decode payload", http.StatusBadRequest)
|
return http.StatusBadRequest, fmt.Errorf("decode payload: %w", err)
|
||||||
return
|
}
|
||||||
|
if err := h.dispatcher.HandlePush(p); err != nil {
|
||||||
|
return http.StatusInternalServerError, err
|
||||||
}
|
}
|
||||||
dispatchErr = h.dispatcher.HandlePush(p)
|
|
||||||
default:
|
default:
|
||||||
// Unhandled event types are not an error — the webhook may be
|
// Unhandled event types are not an error — the webhook may be
|
||||||
// subscribed to more events than this bot reacts to.
|
// subscribed to more events than this bot reacts to.
|
||||||
}
|
}
|
||||||
|
|
||||||
if dispatchErr != nil {
|
return http.StatusNoContent, nil
|
||||||
log.Printf("yaju-keisatsu: handling %s event: %v", event, dispatchErr)
|
|
||||||
http.Error(w, "internal error", http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.WriteHeader(http.StatusNoContent)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// validSignature checks X-Forgejo-Signature (falling back to
|
// validSignature checks X-Forgejo-Signature (falling back to
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue