package native_test import ( "context" "io" "net" "net/http" "sync/atomic" "testing" "time" "git.yuntuo.hk/k2safe/go-omni/transport/native" ) func TestServerSlowHeadersCloseBeforeHandler(t *testing.T) { var handlerCalls atomic.Int32 server := native.New(http.HandlerFunc(func(http.ResponseWriter, *http.Request) { handlerCalls.Add(1) })) server.ReadHeaderTimeout = 40 * time.Millisecond listener, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { t.Fatal(err) } done := make(chan error, 1) go func() { done <- server.Serve(context.Background(), listener) }() defer stopServer(t, server, listener, done) waitForServer(t, listener.Addr().String()) conn, err := net.DialTimeout("tcp", listener.Addr().String(), time.Second) if err != nil { t.Fatal(err) } defer conn.Close() if _, err := io.WriteString(conn, "GET /health HTTP/1.1\r\nHost: local"); err != nil { t.Fatal(err) } requirePeerClose(t, conn) if handlerCalls.Load() != 0 { t.Fatal("handler ran before slow headers completed") } } func TestServerSlowChunkedBodyClosesBeforeHandler(t *testing.T) { var handlerCalls atomic.Int32 server := native.New(http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) { if _, err := io.ReadAll(r.Body); err == nil { handlerCalls.Add(1) } })) server.ReadTimeout = 40 * time.Millisecond listener, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { t.Fatal(err) } done := make(chan error, 1) go func() { done <- server.Serve(context.Background(), listener) }() defer stopServer(t, server, listener, done) waitForServer(t, listener.Addr().String()) conn, err := net.DialTimeout("tcp", listener.Addr().String(), time.Second) if err != nil { t.Fatal(err) } defer conn.Close() request := "POST /body HTTP/1.1\r\nHost: local\r\nTransfer-Encoding: chunked\r\n\r\n4\r\npa" if _, err := io.WriteString(conn, request); err != nil { t.Fatal(err) } requirePeerClose(t, conn) if handlerCalls.Load() != 0 { t.Fatal("handler ran before slow chunked body completed") } }