package main import ( "crypto/subtle" "log" "net/http" "runtime/debug" "time" ) func chain(h http.Handler, mws ...func(http.Handler) http.Handler) http.Handler { for i := len(mws) - 1; i >= 0; i-- { h = mws[i](h) } return h } func recoverMW(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { defer func() { if rec := recover(); rec != nil { log.Printf("panic %s %s: %v\n%s", r.Method, r.URL.Path, rec, debug.Stack()) http.Error(w, "internal error", http.StatusInternalServerError) } }() next.ServeHTTP(w, r) }) } type statusRecorder struct { http.ResponseWriter status int } func (sr *statusRecorder) WriteHeader(code int) { sr.status = code sr.ResponseWriter.WriteHeader(code) } func accessLogMW(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { start := time.Now() sr := &statusRecorder{ResponseWriter: w, status: http.StatusOK} next.ServeHTTP(sr, r) log.Printf("%s %s %d %s", r.Method, r.URL.Path, sr.status, time.Since(start)) }) } func verifyTelegramSecret(provided, expected string) bool { if expected == "" { return false } return subtle.ConstantTimeCompare([]byte(provided), []byte(expected)) == 1 }