mirror of
https://github.com/siderolabs/omni.git
synced 2025-08-08 02:27:00 +02:00
Currently, if gateway meets existing X-Forwarded-For header, it will append peer address that it sees to the existing value using comma. Our IP extraction function didn't account for that, and so it failed to parse IP and it used the original `peer.address` which set deep below in the gRPC middleware. This commit ensures that we try to split the string value using `,`. Closes #668 Signed-off-by: Dmitriy Matrenichev <dmitry.matrenichev@siderolabs.com>
75 lines
1.8 KiB
Go
75 lines
1.8 KiB
Go
// Copyright (c) 2024 Sidero Labs, Inc.
|
|
//
|
|
// Use of this software is governed by the Business Source License
|
|
// included in the LICENSE file.
|
|
|
|
package logging
|
|
|
|
import (
|
|
"net"
|
|
"net/http"
|
|
|
|
"github.com/felixge/httpsnoop"
|
|
"github.com/grpc-ecosystem/go-grpc-middleware/logging/zap/ctxzap"
|
|
grpc_ctxtags "github.com/grpc-ecosystem/go-grpc-middleware/tags"
|
|
"go.uber.org/zap"
|
|
"go.uber.org/zap/zapcore"
|
|
)
|
|
|
|
// Handler adds structured logging to each request going through a wrapped handler.
|
|
type Handler struct {
|
|
h http.Handler
|
|
logger *zap.Logger
|
|
fields []zap.Field
|
|
}
|
|
|
|
// ServeHTTP implements http.Handler.
|
|
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
remoteAddr := r.RemoteAddr
|
|
remoteAddr, _, _ = net.SplitHostPort(remoteAddr) //nolint:errcheck
|
|
|
|
if realIP := r.Header.Get("X-Forwarded-For"); realIP != "" {
|
|
remoteAddr = realIP
|
|
}
|
|
|
|
logger := h.logger.With(
|
|
zap.String("request_url", r.RequestURI),
|
|
zap.String("method", r.Method),
|
|
zap.String("remote_addr", remoteAddr),
|
|
).With(h.fields...)
|
|
|
|
// inject empty ctxtags and logger into request context
|
|
r = r.WithContext(
|
|
ctxzap.ToContext(
|
|
grpc_ctxtags.SetInContext(r.Context(), grpc_ctxtags.NewTags()),
|
|
logger,
|
|
),
|
|
)
|
|
|
|
metrics := httpsnoop.CaptureMetrics(h.h, w, r)
|
|
|
|
// get injected ctxtags back
|
|
ctxtags := grpc_ctxtags.Extract(r.Context()).Values()
|
|
fields := make([]zapcore.Field, 0, len(ctxtags))
|
|
|
|
for k, v := range ctxtags {
|
|
fields = append(fields, zap.Any(k, v))
|
|
}
|
|
|
|
logger.Info("HTTP request done",
|
|
append(
|
|
[]zapcore.Field{
|
|
zap.Duration("duration", metrics.Duration),
|
|
zap.Int("status", metrics.Code),
|
|
zap.Int64("response_length", metrics.Written),
|
|
},
|
|
fields...,
|
|
)...,
|
|
)
|
|
}
|
|
|
|
// NewHandler creates new Handler.
|
|
func NewHandler(h http.Handler, logger *zap.Logger) *Handler {
|
|
return &Handler{h: h, logger: logger}
|
|
}
|