Files
x/handler/http/helpers_test.go
T
ginuerzh a33c6f4a92 test(handler/http): add 25+ tests for probe resistance, MITM, bypass, and edge cases
+698/-3 across auth_test, connect_test, handler_test, metadata_test,
proxy_test, and websocket_test. Covers probeResistanceResponse (web/file/
host/code types), handleRequest (bypass/UDP-disabled/CONNECT edge cases),
setupTrafficLimiter with observer, observeStats lifecycle, MITM metadata,
HTTP/1.0 keep-alive proxyRoundTrip, websocket body recording, and sniff
timeout handling. Fixes SetDeadline signatures from any→time.Time.
2026-05-30 17:54:27 +08:00

109 lines
3.9 KiB
Go

package http
import (
"context"
"net"
"strings"
"sync"
"time"
"github.com/go-gost/core/handler"
"github.com/go-gost/core/logger"
"github.com/go-gost/core/observer"
cmdata "github.com/go-gost/core/metadata"
xmetadata "github.com/go-gost/x/metadata"
)
// --- Shared test helpers ---
// testLogger implements logger.Logger for testing. It discards all output.
type testLogger struct{}
func (l *testLogger) WithFields(fields map[string]any) logger.Logger { return l }
func (l *testLogger) Debug(args ...any) {}
func (l *testLogger) Debugf(format string, args ...any) {}
func (l *testLogger) Info(args ...any) {}
func (l *testLogger) Infof(format string, args ...any) {}
func (l *testLogger) Warn(args ...any) {}
func (l *testLogger) Warnf(format string, args ...any) {}
func (l *testLogger) Error(args ...any) {}
func (l *testLogger) Errorf(format string, args ...any) {}
func (l *testLogger) Fatal(args ...any) {}
func (l *testLogger) Fatalf(format string, args ...any) {}
func (l *testLogger) GetLevel() logger.LogLevel { return logger.InfoLevel }
func (l *testLogger) IsLevelEnabled(level logger.LogLevel) bool { return false }
func (l *testLogger) Trace(args ...any) {}
func (l *testLogger) Tracef(format string, args ...any) {}
// testObserver implements observer.Observer for testing.
type testObserver struct{}
func (o *testObserver) Observe(ctx context.Context, events []observer.Event, opts ...observer.Option) error {
return nil
}
// testMD creates metadata from a map for testing.
func testMD(m map[string]any) cmdata.Metadata {
return xmetadata.NewMetadata(m)
}
// --- Handler factory helpers ---
// newTestHandler creates an httpHandler with default test settings.
// Pass additional options to override defaults.
func newTestHandler(opts ...handler.Option) *httpHandler {
options := handler.Options{
Logger: &testLogger{},
}
for _, opt := range opts {
opt(&options)
}
h := &httpHandler{
options: options,
}
return h
}
// newInitdHandler creates an httpHandler and calls Init with empty metadata.
func newInitdHandler(opts ...handler.Option) *httpHandler {
h := newTestHandler(opts...)
_ = h.Init(testMD(map[string]any{}))
return h
}
// --- stringConn: in-memory net.Conn for tests ---
// stringConn is an in-memory net.Conn implementation for testing.
// It reads from a prepopulated buffer and captures writes into a separate
// buffer. Useful for testing code that writes HTTP responses without
// needing net.Pipe() + goroutine.
type stringConn struct {
readBuf *strings.Reader
writeBuf *strings.Builder
closed bool
mu sync.Mutex
}
func newStringConn(data string) *stringConn {
return &stringConn{
readBuf: strings.NewReader(data),
writeBuf: &strings.Builder{},
}
}
func (c *stringConn) Read(b []byte) (int, error) { return c.readBuf.Read(b) }
func (c *stringConn) Write(b []byte) (int, error) { return c.writeBuf.Write(b) }
func (c *stringConn) Close() error {
c.mu.Lock()
defer c.mu.Unlock()
c.closed = true
return nil
}
func (c *stringConn) LocalAddr() net.Addr { return &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 8080} }
func (c *stringConn) RemoteAddr() net.Addr { return &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 12345} }
func (c *stringConn) SetDeadline(t time.Time) error { return nil }
func (c *stringConn) SetReadDeadline(t time.Time) error { return nil }
func (c *stringConn) SetWriteDeadline(t time.Time) error { return nil }
func (c *stringConn) Bytes() []byte { return []byte(c.writeBuf.String()) }
func (c *stringConn) String() string { return c.writeBuf.String() }