Middleware para o framework Gin que captura automaticamente todas as requisições HTTP e envia eventos de auditoria imutáveis para o ImmutableLog.
Usa c.Next() para capturar o status após todos os handlers, goroutine fire-and-forget para zero overhead na resposta.
go get github.com/gin-gonic/ginNenhuma outra dependência. O envio ao ImmutableLog usa net/http da stdlib.
Copie middleware.go para dentro do seu projeto:
internal/middleware/immutablelog.go
pkg/immutablelog/middleware.go
| Variável | Obrigatório | Default | Descrição |
|---|---|---|---|
IMTBL_API_KEY |
Sim | — | Chave de API do ImmutableLog |
IMTBL_SERVICE_NAME |
Não | "" (usa Config.ServiceName) |
Nome do serviço exibido nos eventos |
IMTBL_ENV |
Não | "" (usa Config.Env) |
Ambiente de execução |
Segurança: nunca exponha
IMTBL_API_KEYem código. Use variáveis de ambiente ou secrets manager.
package main
import (
"github.com/gin-gonic/gin"
"github.com/yourorg/yourapp/internal/middleware"
)
func main() {
r := gin.Default()
// Registro global — aplica a todas as rotas
r.Use(middleware.Middleware(middleware.Config{
APIKey: "iml_live_xxxx",
ServiceName: "my-api",
Env: "production",
SkipPaths: []string{"/health", "/metrics", "/ping"},
}))
r.GET("/health", func(c *gin.Context) { c.JSON(200, gin.H{"ok": true}) })
r.POST("/payments", paymentsHandler)
r.Run(":8080")
}| Etapa | Descrição |
|---|---|
c.Next() |
Executa toda a cadeia de handlers — status capturado depois |
go emit() |
Goroutine fire-and-forget — zero latência adicionada à resposta |
c.Get() |
Lê imtbl.eventName definido pelo handler para nome semântico |
| SHA-256 | Hash do body — nunca o conteúdo bruto é enviado ao ImmutableLog |
func paymentsHandler(c *gin.Context) {
c.Set("imtbl.eventName", "payment.created")
// ... lógica de negócio ...
c.JSON(201, gin.H{"ok": true})
}// Auditar apenas um grupo de rotas
api := r.Group("/api/v1")
api.Use(middleware.Middleware(middleware.Config{
APIKey: os.Getenv("IMTBL_API_KEY"),
ServiceName: "api-v1",
Env: os.Getenv("APP_ENV"),
}))
api.POST("/payments", paymentsHandler)
r.GET("/health", healthHandler) // não auditado| Situação | Resultado |
|---|---|
APIKey vazio |
Evento enviado sem auth (falha no servidor) |
Path em SkipPaths |
Evento ignorado, c.Next() chamado normalmente |
| Status 2xx | type: success |
| Status 3xx | type: info |
| Status 4xx / 5xx | type: error |
c.Abort() em auth |
Audit captura o status — registre audit ANTES do auth |
| Falha no POST | Silenciada na goroutine — nunca quebra a aplicação |