Webhook fogadó JSON logolással: hookrelay
A Gitea-m tud webhook-ot küldeni minden push-nál. A kérdés az volt: hova küldje? Egy egyszerű szerver kell ami fogadja a payload-ot és elmenti – nem kell feldolgozni, nem kell továbbítani, csak logolni.
A hookrelay pontosan ennyi. Két végpont: /health az életjelhez, /webhook a payload fogadásához. Minden bejövő webhook egy JSON sor a log fájlban.
POST validáció
A stackctl-ben minden végpont GET volt. A hookrelay-nél a /webhook csak POST-ot fogad el – ez az első projekt ahol a HTTP metódust is ellenőrizni kell:
if r.Method != http.MethodPost {
http.Error(w, "POST only", http.StatusMethodNotAllowed)
return
}
A http.StatusMethodNotAllowed a 405-ös HTTP kód. A Go net/http csomagja minden standard kódhoz ad konstanst – nem kell fejből tudni a számokat.
JSON dekódolás
A bejövő payload-ot a json.NewDecoder olvassa be közvetlenül a request body-ból:
var hook Webhook
err := json.NewDecoder(r.Body).Decode(&hook)
Ez elegánsabb mint a teljes body beolvasása és utána az Unmarshal – a decoder stream-ből dolgozik, nem tölti be az egészet a memóriába. Kis payload-oknál nincs különbség, de a minta jó.
A production ready verzióban az event mező is ellenőrzésre kerül – ha üres, 400-as hibát kap a küldő. Az eredeti verzió ezt nem csinálta.
Fájlba írás append módban
A log fájlt os.OpenFile-lal nyitom append módban:
f, _ := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644)
A három flag együtt: ha nem létezik a fájl, létrehozza. Ha létezik, a végére ír. Csak írásra nyitja meg. Ez pontosan az amit bash-ben a >> operátor csinál.
Minden webhook egy JSON sor – ez a JSON Lines formátum. Könnyű olvasni jq-val, könnyű grep-pelni, és könnyű feldolgozni.
A logger interface
A deployer-nél és az sshping-nél már tanultam az interface-alapú tesztelést. A hookrelay-nél a logger interface absztrahálja a fájlba írást:
type logger interface {
save(hook Webhook) error
}
A valódi fileLogger fájlba ír. A teszt mockLogger egy slice-ba gyűjti a webhook-okat. Így a HTTP handler tesztelhető anélkül hogy fájlrendszert érintene – és a fileLogger-t külön teszteljük temp fájlokkal.
Tesztek
A hookrelay tesztjei kombináció: httptest a handler-ekhez, mock logger a webhook feldolgozáshoz, temp fájlok a fileLogger-hez. Ez lefedi a teljes működést: valid payload, hibás JSON, rossz metódus, hiányzó mező, fájlba írás, append viselkedés.
Mit tanultam?
Három új elem az eddigi projektekhez képest:
A POST metódus kezelés és validáció – nem minden request egyforma, és a szerver feladata elmondani mit fogad el.
A JSON Lines formátum – egyszerű, stream-elhető, grep-elhető logolás. Egy sor egy esemény.
Az os.OpenFile flag-ek – hogyan nyiss fájlt pontosan úgy ahogy kell: append, create, write-only. Ez a Go-ban explicit, bash-ben a >> mögé van rejtve.
Hogyan próbáld ki?
git clone https://github.com/brtkcs/werkstatt-tools.git
cd werkstatt-tools/hookrelay
go run main.go
Egy másik terminálból:
curl -X POST localhost:8080/webhook \
-d '{"event":"push","repo":"werkstatt","branch":"main"}'
cat webhooks.log
A teljes forráskód a werkstatt-tools repóban.