MCPcopy
hub / github.com/unkeyed/unkey / ServeHTTP

Method ServeHTTP

svc/ctrl/api/github_webhook.go:34–92  ·  view source on GitHub ↗

ServeHTTP validates the webhook signature and dispatches to event-specific handlers. Currently supports push events for triggering deployments. Unknown event types are acknowledged with 200 OK but not processed.

(w http.ResponseWriter, r *http.Request)

Source from the content-addressed store, hash-verified

32// handlers. Currently supports push events for triggering deployments.
33// Unknown event types are acknowledged with 200 OK but not processed.
34func (s *GitHubWebhook) ServeHTTP(w http.ResponseWriter, r *http.Request) {
35 logger.Info("GitHub webhook request received",
36 "method", r.Method,
37 "path", r.URL.Path,
38 "remote_addr", r.RemoteAddr,
39 )
40
41 if r.Method != http.MethodPost {
42 logger.Warn("GitHub webhook rejected: method not allowed", "method", r.Method)
43 http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
44 return
45 }
46
47 event := r.Header.Get("X-GitHub-Event")
48 if event == "" {
49 http.Error(w, "missing X-GitHub-Event header", http.StatusBadRequest)
50 return
51 }
52
53 signature := r.Header.Get("X-Hub-Signature-256")
54 if signature == "" {
55 logger.Warn("GitHub webhook rejected: missing signature header")
56 http.Error(w, "missing X-Hub-Signature-256 header", http.StatusUnauthorized)
57 return
58 }
59
60 body, err := io.ReadAll(http.MaxBytesReader(w, r.Body, maxWebhookBodySize))
61 if err != nil {
62 logger.Warn("GitHub webhook rejected: failed to read body", "error", err)
63 http.Error(w, "failed to read body", http.StatusBadRequest)
64 return
65 }
66
67 if !githubclient.VerifyWebhookSignature(body, signature, s.webhookSecret) {
68 logger.Warn("GitHub webhook rejected: invalid signature")
69 http.Error(w, "invalid signature", http.StatusUnauthorized)
70 return
71 }
72
73 logger.Info("GitHub webhook signature verified", "event", event)
74
75 deliveryID := r.Header.Get("X-GitHub-Delivery")
76
77 switch event {
78 case "push":
79 s.handlePush(r.Context(), w, body, deliveryID)
80 case "pull_request":
81 s.handlePullRequest(r.Context(), w, body, deliveryID)
82 case "create", "delete":
83 logger.Info("Branch lifecycle event ignored", "event", event)
84 w.WriteHeader(http.StatusOK)
85 case "installation":
86 logger.Info("Installation event received")
87 w.WriteHeader(http.StatusOK)
88 default:
89 logger.Info("Unhandled event type", "event", event)
90 w.WriteHeader(http.StatusOK)
91 }

Calls 6

handlePushMethod · 0.95
handlePullRequestMethod · 0.95
ContextMethod · 0.80
GetMethod · 0.65
ErrorMethod · 0.45
WriteHeaderMethod · 0.45