Telego Webhook Handler Configuration: Complete Guide for Go Bots
Telego webhook handler configuration involves registering a POST handler on your HTTP server using WebhookFastHTTP, WebhookHTTPServer, or WebhookHTTPServeMux, then calling Bot.UpdatesViaWebhook to receive Telegram updates on a Go channel.
The mymmrac/telego library provides a modular architecture for handling Telegram bot webhooks in Go. Instead of forcing a specific HTTP framework, it exposes adapter functions that integrate with fasthttp, net/http, or http.ServeMux, while managing update decoding, channel buffering, and graceful shutdown internally.
Understanding the Telego Webhook Architecture
The webhook system separates transport concerns from update processing. The core components reside in webhook_handler.go (server adapters) and webhook.go (channel management and options).
WebhookHandler Type
The underlying handler signature is defined in webhook.go:
type WebhookHandler func(ctx context.Context, data []byte) error
This function receives the request context and raw JSON body. It must return an error if JSON unmarshaling fails. The UpdatesViaWebhook method wraps this handler to push decoded Update structs onto a buffered channel.
Server Integration Helpers
Three adapter functions in webhook_handler.go bind the WebhookHandler to your server:
WebhookFastHTTP– wraps*fasthttp.ServerWebhookHTTPServer– wraps*http.ServerWebhookHTTPServeMux– registers on*http.ServeMux
Each helper validates the request method (POST only), checks the optional secret token via the X-Telegram-Bot-Api-Secret-Token header, and returns appropriate HTTP status codes (404, 405, 401, or 200).
Configuring Webhook Handlers for Different Servers
FastHTTP Configuration
For high-performance applications using valyala/fasthttp, use WebhookFastHTTP. The function returns a closure that accepts your WebhookHandler.
package main
import (
"context"
"fmt"
"os"
"github.com/valyala/fasthttp"
"github.com/mymmrac/telego"
)
func main() {
ctx := context.Background()
botToken := os.Getenv("TOKEN")
bot, err := telego.NewBot(botToken, telego.WithDefaultDebugLogger())
if err != nil {
panic(err)
}
// Optional: configure webhook on Telegram servers
_ = bot.SetWebhook(ctx, &telego.SetWebhookParams{
URL: "https://my.domain/bot",
SecretToken: bot.SecretToken(),
})
// Initialize FastHTTP server
fsrv := &fasthttp.Server{}
// Configure webhook handler with 256-slot buffer
updates, err := bot.UpdatesViaWebhook(
ctx,
telego.WebhookFastHTTP(fsrv, "/bot", bot.SecretToken()),
telego.WithWebhookBuffer(256),
)
if err != nil {
panic(err)
}
// Start server in background
go func() { _ = fsrv.ListenAndServe(":8443") }()
// Process updates
for upd := range updates {
fmt.Printf("Update %d: %+v\n", upd.UpdateID, upd)
}
}
This example mirrors the official implementation in [examples/updates_webhook/main.go](https://github.com/mymmrac/telego/blob/main/examples/updates_webhook/main.go).
Standard Library http.Server
For applications using net/http, WebhookHTTPServer provides identical validation logic:
srv := &http.Server{Addr: ":8080"}
updates, err := bot.UpdatesViaWebhook(
ctx,
telego.WebhookHTTPServer(srv, "/bot", bot.SecretToken()),
telego.WithWebhookSet(ctx, &telego.SetWebhookParams{
URL: "https://my.domain/bot",
SecretToken: bot.SecretToken(),
}),
)
if err != nil { panic(err) }
go func() { _ = srv.ListenAndServe() }()
for upd := range updates {
// Handle update
}
Using http.ServeMux
When multiplexing multiple handlers, WebhookHTTPServeMux registers the POST route directly:
mux := http.NewServeMux()
updates, err := bot.UpdatesViaWebhook(
ctx,
telego.WebhookHTTPServeMux(mux, "POST /bot", bot.SecretToken()),
telego.WithWebhookBuffer(128),
)
if err != nil { panic(err) }
go func() { _ = http.ListenAndServe(":8080", mux) }()
for upd := range updates {
// Process update
}
Processing Updates with UpdatesViaWebhook
The Bot.UpdatesViaWebhook method in webhook.go orchestrates the entire flow:
- State validation – ensures no conflicting long-polling or webhook process is running (
b.run(runningWebhook)). - Option application – applies
WebhookOptionfunctions to configure the internalwebhookstruct. - Channel creation – initializes a buffered
chan Updatewith size determined byWithWebhookBuffer(default: 128). - Handler registration – invokes the provided
registerHandlerclosure, supplying aWebhookHandlerthat unmarshals JSON and sends updates to the channel. - Lifecycle management – spawns a goroutine that closes the channel and clears state when the context is cancelled.
Channel Buffering Options
Control memory usage and backpressure with WithWebhookBuffer:
updates, err := bot.UpdatesViaWebhook(
ctx,
telego.WebhookFastHTTP(srv, "/bot"),
telego.WithWebhookBuffer(64), // Small buffer for low-traffic bots
)
The default buffer size of 128 is defined as defaultWebhookUpdateChanBuffer in webhook.go.
Automatic Webhook Registration
Avoid manual SetWebhook calls by using WithWebhookSet:
updates, err := bot.UpdatesViaWebhook(
ctx,
telego.WebhookHTTPServer(srv, "/bot"),
telego.WithWebhookSet(ctx, &telego.SetWebhookParams{
URL: "https://api.example.com/bot",
SecretToken: bot.SecretToken(),
MaxConnections: 40,
}),
)
This option invokes bot.SetWebhook before starting the server, ensuring Telegram knows where to deliver updates.
Summary
- Telego webhook handler configuration relies on adapter functions (
WebhookFastHTTP,WebhookHTTPServer,WebhookHTTPServeMux) to bridge your HTTP server with the library's update processing. - The
WebhookHandlertype receives raw JSON bytes and is responsible for unmarshaling and channel delivery;UpdatesViaWebhookorchestrates this into a buffered<-chan Update. - File locations: server adapters live in
webhook_handler.go, core logic inwebhook.go, and runnable examples inexamples/updates_webhook/main.go. - Options like
WithWebhookBufferandWithWebhookSettune performance and automate webhook registration with Telegram's API.
Frequently Asked Questions
How do I secure my Telego webhook endpoint?
Pass your secret token to the server adapter function (e.g., WebhookFastHTTP(server, "/bot", bot.SecretToken())). The handler validates the X-Telegram-Bot-Api-Secret-Token header against this value, returning HTTP 401 if the token mismatch indicates a forged request. You can retrieve the bot's auto-generated secret token via bot.SecretToken().
What is the difference between UpdatesViaWebhook and UpdatesViaLongPolling?
UpdatesViaWebhook configures the bot to receive updates via an HTTP POST endpoint that Telegram pushes to, while UpdatesViaLongPolling repeatedly calls the getUpdates method to fetch updates from Telegram's servers. The webhook approach is more efficient for high-traffic bots and provides lower latency, but requires a publicly accessible HTTPS server. UpdatesViaWebhook lives in webhook.go and uses a channel-based architecture, whereas long polling is implemented in long_polling.go.
Can I use a custom HTTP server not supported by the built-in helpers?
Yes. The UpdatesViaWebhook method accepts any function matching func(handler WebhookHandler) error as the registerHandler parameter. Implement your own registration logic that validates the request method, verifies the secret token header, reads the body, and calls handler(ctx, body). This allows integration with frameworks like Gin, Echo, or Fiber by wrapping their request contexts into the standard WebhookHandler signature.
How do I handle graceful shutdown when using webhooks?
The UpdatesViaWebhook method accepts a context.Context. When this context is cancelled (e.g., via signal.NotifyContext on SIGINT), the library automatically closes the update channel and clears the internal runningWebhook state. Ensure your HTTP server also implements graceful shutdown (e.g., http.Server.Shutdown) to complete processing of in-flight requests before the program exits. The channel returned by UpdatesViaWebhook will be closed, causing any for upd := range updates loops to exit cleanly.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →