This commit is contained in:
Vicente Ferrari Smith 2026-05-20 07:50:56 +02:00
parent 65326b0ff5
commit 2900582eb4
5 changed files with 24 additions and 12 deletions

View File

@ -79,6 +79,7 @@ type contextKey string
const userKey contextKey = "web_user" const userKey contextKey = "web_user"
const permissionsKey contextKey = "web_permissions" const permissionsKey contextKey = "web_permissions"
const RequestBodyKey contextKey = "request_body"
func SetUser(r *http.Request, user *data.User) *http.Request { func SetUser(r *http.Request, user *data.User) *http.Request {
return r.WithContext(context.WithValue(r.Context(), userKey, user)) return r.WithContext(context.WithValue(r.Context(), userKey, user))

View File

@ -1,6 +1,7 @@
package common package common
import ( import (
"bytes"
"crypto/rand" "crypto/rand"
"crypto/rsa" "crypto/rsa"
"crypto/x509" "crypto/x509"
@ -128,8 +129,12 @@ func ReadCSV(qs url.Values, key string, defaultValue []string) []string {
// ── Error responses ────────────────────────────────────────────────────────── // ── Error responses ──────────────────────────────────────────────────────────
func (app *Application) LogError(r *http.Request, err error) { func (app *Application) LogError(r *http.Request, err error) {
app.Logger.PrintError(err, map[string]string{ props := map[string]string{
"request_method": r.Method, "request_method": r.Method,
"request_url": r.URL.String(), "request_url": r.URL.String(),
}) }
if buf, ok := r.Context().Value(RequestBodyKey).(*bytes.Buffer); ok && buf.Len() > 0 {
props["request_body"] = buf.String()
}
app.Logger.PrintError(err, props)
} }

View File

@ -1,7 +1,10 @@
package common package common
import ( import (
"bytes"
"context"
"expvar" "expvar"
"io"
"net/http" "net/http"
"strconv" "strconv"
"sync" "sync"
@ -9,6 +12,15 @@ import (
"github.com/felixge/httpsnoop" "github.com/felixge/httpsnoop"
) )
func (app *Application) CaptureBody(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
buf := &bytes.Buffer{}
r.Body = io.NopCloser(io.TeeReader(r.Body, buf))
ctx := context.WithValue(r.Context(), RequestBodyKey, buf)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
var ( var (
metricsOnce sync.Once metricsOnce sync.Once
metricTotalRequests *expvar.Int metricTotalRequests *expvar.Int

View File

@ -40,7 +40,7 @@ func routes(app *common.Application) http.Handler {
apiMux.HandleFunc("GET /v1/parlament/votes/{path...}", api.GetParlVoteDetail) apiMux.HandleFunc("GET /v1/parlament/votes/{path...}", api.GetParlVoteDetail)
apiMux.Handle("GET /debug/vars", expvar.Handler()) apiMux.Handle("GET /debug/vars", expvar.Handler())
apiChain := app.Metrics(api.RecoverPanic(app.EnableCORS(api.RateLimit(api.Authenticate(apiMux))))) apiChain := app.Metrics(api.RecoverPanic(app.CaptureBody(app.EnableCORS(api.RateLimit(api.Authenticate(apiMux))))))
// ── Web router ────────────────────────────────────────────────────────── // ── Web router ──────────────────────────────────────────────────────────
web := web.Web{ web := web.Web{

View File

@ -4,7 +4,6 @@ import (
"encoding/json" "encoding/json"
"io" "io"
"os" "os"
"runtime/debug"
"sync" "sync"
"time" "time"
) )
@ -67,18 +66,13 @@ func (l *Logger) print(level Level, message string, properties map[string]string
Time string `json:"time"` Time string `json:"time"`
Message string `json:"message"` Message string `json:"message"`
Properties map[string]string `json:"properties,omitempty"` Properties map[string]string `json:"properties,omitempty"`
Trace string `json:"trace,omitempty"`
}{ }{
Level: level.String(), Level: level.String(),
Time: time.Now().UTC().Format(time.RFC3339), Time: time.Now().UTC().Format(time.RFC3339),
Message: message, Message: message,
Properties: properties, Properties: properties,
} }
if level >= LevelError {
aux.Trace = string(debug.Stack())
}
var line []byte var line []byte
line, err := json.Marshal(aux) line, err := json.Marshal(aux)