mirror of
https://github.com/go-gost/x.git
synced 2026-10-19 16:16:32 +00:00
fix: prevent double-recording when HTTP response cache is enabled
The cache-hit path (serveCachedResponse) recorded on the same HandlerRecorderObject as the calling handler's deferred Record(), producing two records per request. Copy ro at HandleHTTP entry so the sniffer's internal recording stays isolated from the caller's defer. Also zero ro.Time when the sniffer takes over, so the handler's defer Record() skips the now-redundant connection-level record. Fixes 10 files across sniffer and all 8 handlers that support sniffed HTTP forwarding.
This commit is contained in:
@@ -232,6 +232,7 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand
|
||||
conn = xnet.NewReadWriteConn(br, conn, conn)
|
||||
handled, sniffErr := h.handleSniffedProtocol(ctx, conn, ro, log, proto)
|
||||
if handled {
|
||||
ro.Time = time.Time{}
|
||||
return sniffErr
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,6 +228,7 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand
|
||||
conn = xnet.NewReadWriteConn(br, conn, conn)
|
||||
handled, sniffErr := h.handleSniffedProtocol(ctx, conn, ro, log, proto)
|
||||
if handled {
|
||||
ro.Time = time.Time{}
|
||||
return sniffErr
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +80,7 @@ func (h *httpHandler) handleConnect(ctx context.Context, conn net.Conn, ro *xrec
|
||||
if h.md.sniffing {
|
||||
snifferHandled, err = h.sniffAndHandle(ctx, conn, cc, ro, log)
|
||||
if snifferHandled {
|
||||
ro.Time = time.Time{}
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,6 +227,7 @@ func (h *redirectHandler) Handle(ctx context.Context, conn net.Conn, opts ...han
|
||||
conn = xnet.NewReadWriteConn(br, conn, conn)
|
||||
switch proto {
|
||||
case sniffing.ProtoHTTP:
|
||||
ro.Time = time.Time{}
|
||||
return sniffer.HandleHTTP(ctx, "tcp", conn,
|
||||
sniffing.WithService(h.options.Service),
|
||||
sniffing.WithDial(dial),
|
||||
|
||||
@@ -233,6 +233,7 @@ func (h *relayHandler) handleConnect(ctx context.Context, conn net.Conn, network
|
||||
conn = xnet.NewReadWriteConn(br, conn, conn)
|
||||
switch proto {
|
||||
case sniffing.ProtoHTTP:
|
||||
ro.Time = time.Time{}
|
||||
return sniffer.HandleHTTP(ctx, "tcp", conn,
|
||||
sniffing.WithService(h.options.Service),
|
||||
sniffing.WithDial(dial),
|
||||
@@ -242,6 +243,7 @@ func (h *relayHandler) handleConnect(ctx context.Context, conn net.Conn, network
|
||||
sniffing.WithLog(log),
|
||||
)
|
||||
case sniffing.ProtoTLS:
|
||||
ro.Time = time.Time{}
|
||||
return sniffer.HandleTLS(ctx, "tcp", conn,
|
||||
sniffing.WithService(h.options.Service),
|
||||
sniffing.WithDial(dial),
|
||||
|
||||
@@ -189,6 +189,7 @@ func (h *sniHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler.
|
||||
conn = xnet.NewReadWriteConn(br, conn, conn)
|
||||
handled, sniffErr := h.handleSniffedProtocol(ctx, conn, ro, log, proto)
|
||||
if handled {
|
||||
ro.Time = time.Time{}
|
||||
return sniffErr
|
||||
}
|
||||
|
||||
|
||||
@@ -233,6 +233,7 @@ func (h *ssHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler.H
|
||||
conn = xnet.NewReadWriteConn(br, conn, conn)
|
||||
switch proto {
|
||||
case sniffing.ProtoHTTP:
|
||||
ro.Time = time.Time{}
|
||||
return sniffer.HandleHTTP(ctx, "tcp", conn,
|
||||
sniffing.WithService(h.options.Service),
|
||||
sniffing.WithDial(dial),
|
||||
@@ -242,6 +243,7 @@ func (h *ssHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler.H
|
||||
sniffing.WithLog(log),
|
||||
)
|
||||
case sniffing.ProtoTLS:
|
||||
ro.Time = time.Time{}
|
||||
return sniffer.HandleTLS(ctx, "tcp", conn,
|
||||
sniffing.WithService(h.options.Service),
|
||||
sniffing.WithDial(dial),
|
||||
|
||||
@@ -177,6 +177,7 @@ func (h *unixHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler
|
||||
conn = xnet.NewReadWriteConn(br, conn, conn)
|
||||
switch proto {
|
||||
case sniffing.ProtoHTTP:
|
||||
ro.Time = time.Time{}
|
||||
return sniffer.HandleHTTP(ctx, "tcp", conn,
|
||||
sniffing.WithService(h.options.Service),
|
||||
sniffing.WithDial(dial),
|
||||
@@ -186,6 +187,7 @@ func (h *unixHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler
|
||||
sniffing.WithLog(log),
|
||||
)
|
||||
case sniffing.ProtoTLS:
|
||||
ro.Time = time.Time{}
|
||||
return sniffer.HandleTLS(ctx, "tcp", conn,
|
||||
sniffing.WithService(h.options.Service),
|
||||
sniffing.WithDial(dial),
|
||||
|
||||
@@ -70,6 +70,13 @@ func (h *Sniffer) HandleHTTP(ctx context.Context, conn net.Conn, opts ...HandleO
|
||||
|
||||
ro := ho.recorderObject
|
||||
|
||||
// Copy ro so that all internal recording (cache-hit serveCachedResponse
|
||||
// and cache-miss httpRoundTrip) happens on a local clone, preventing
|
||||
// double-record when the caller's defer also records ro.
|
||||
ro2 := &xrecorder.HandlerRecorderObject{}
|
||||
*ro2 = *ro
|
||||
ro = ro2
|
||||
|
||||
if clientIP := xhttp.GetClientIP(req); clientIP != nil {
|
||||
clientAddr := &net.TCPAddr{IP: clientIP}
|
||||
ro.ClientAddr = clientAddr.String()
|
||||
|
||||
@@ -52,6 +52,13 @@ func (h *Sniffer) HandleHTTP(ctx context.Context, network string, conn net.Conn,
|
||||
|
||||
ro := ho.recorderObject
|
||||
|
||||
// Copy ro so that all internal recording (cache-hit serveCachedResponse
|
||||
// and cache-miss httpRoundTrip) happens on a local clone, preventing
|
||||
// double-record when the caller's defer also records ro.
|
||||
ro2 := &xrecorder.HandlerRecorderObject{}
|
||||
*ro2 = *ro
|
||||
ro = ro2
|
||||
|
||||
if clientIP := xhttp.GetClientIP(req); clientIP != nil {
|
||||
ro.ClientIP = clientIP.String()
|
||||
ctx = xctx.ContextWithSrcAddr(ctx, &net.TCPAddr{IP: clientIP})
|
||||
|
||||
Reference in New Issue
Block a user