Files
x/internal/util/sniffing/sniffer_rewrite.go
T
ginuerzh 4f526c2aee refactor(sniffing): split sniffer monolith into focused files, extract testable helpers
Split ~850-line sniffer.go into 6 focused files (http, h2, tls, ws,
rewrite, test), extract pure helpers (clampBodySize, normalizeHost,
effectiveReadTimeout), fix "DeafultSampleRate" typo, add doc comments
on all exported symbols, and add 22 unit tests.
2026-05-27 21:21:40 +08:00

46 lines
1.4 KiB
Go

package sniffing
import (
"context"
"fmt"
"io"
"net/http"
"strings"
"github.com/go-gost/core/logger"
xnet "github.com/go-gost/x/internal/net"
xrecorder "github.com/go-gost/x/recorder"
"golang.org/x/net/http/httpguts"
)
// upgradeType extracts the Upgrade protocol from an HTTP header if the
// Connection header contains the "Upgrade" token.
func upgradeType(h http.Header) string {
if !httpguts.HeaderValuesContainsToken(h["Connection"], "Upgrade") {
return ""
}
return h.Get("Upgrade")
}
// handleUpgradeResponse handles HTTP 101 Switching Protocols responses.
// It validates the upgrade type, writes the response, and either begins
// WebSocket frame sniffing or falls through to bidirectional copy.
func (h *Sniffer) handleUpgradeResponse(ctx context.Context, rw, cc io.ReadWriteCloser, req *http.Request, res *http.Response, ro *xrecorder.HandlerRecorderObject, log logger.Logger) error {
reqUpType := upgradeType(req.Header)
resUpType := upgradeType(res.Header)
if !strings.EqualFold(reqUpType, resUpType) {
return fmt.Errorf("backend tried to switch protocol %q when %q was requested", resUpType, reqUpType)
}
res.Body = nil
if err := res.Write(rw); err != nil {
return fmt.Errorf("response write: %v", err)
}
if reqUpType == "websocket" && h.Websocket {
return h.sniffingWebsocketFrame(ctx, rw, cc, ro, log)
}
return xnet.Pipe(ctx, rw, cc)
}