Files
telegram-gateway/server.go
Gabriel Radureau d8b102fbf9
All checks were successful
Docker Build / build-and-push-image (push) Successful in 42s
server: don't reject Telegram updates with unknown fields
DisallowUnknownFields rejected real Telegram payloads (entities, from,
date, etc. that our minimal structs don't cover). Lenient decode is the
right default for an upstream webhook we don't control.
2026-05-09 13:06:40 +02:00

77 lines
1.9 KiB
Go

package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"strings"
)
type Server struct {
registry *Registry
}
func NewServer(r *Registry) *Server {
return &Server{registry: r}
}
func (s *Server) Routes() http.Handler {
mux := http.NewServeMux()
mux.HandleFunc("/healthz", s.health)
mux.HandleFunc("/readyz", s.ready)
mux.HandleFunc("/bot/", s.botWebhook)
return chain(mux, recoverMW, accessLogMW)
}
func (s *Server) health(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusOK)
_, _ = fmt.Fprint(w, "OK")
}
func (s *Server) ready(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusOK)
_, _ = fmt.Fprint(w, "OK")
}
func (s *Server) botWebhook(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
slug := strings.TrimPrefix(r.URL.Path, "/bot/")
slug = strings.Trim(slug, "/")
if slug == "" || strings.Contains(slug, "/") {
http.Error(w, "bot slug missing or malformed", http.StatusBadRequest)
return
}
bot, ok := s.registry.Get(slug)
if !ok {
http.Error(w, "unknown bot", http.StatusNotFound)
return
}
if !verifyTelegramSecret(r.Header.Get("X-Telegram-Bot-Api-Secret-Token"), bot.Secret) {
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
var update Update
// NOTE: pas de DisallowUnknownFields — Telegram ajoute des champs
// (entities, sticker, photo, forum_topic…) au fil du temps. On reste
// tolérant et on n'extrait que ce dont on a besoin.
if err := json.NewDecoder(r.Body).Decode(&update); err != nil {
http.Error(w, "bad update payload", http.StatusBadRequest)
return
}
if err := bot.Handler.Handle(r.Context(), update, bot); err != nil {
log.Printf("bot=%s update=%d handler error: %v", slug, update.UpdateID, err)
}
w.WriteHeader(http.StatusOK)
_, _ = fmt.Fprint(w, "{}")
}