package http import ( "bufio" "context" "io" "net" stdhttp "net/http" "testing" "time" ) func TestReviewR8AbsoluteHeaderTimeout(t *testing.T) { for _, wrapped := range []bool{false, true} { name := "standard-net-http" if wrapped { name = "silo-listener" } t.Run(name, func(t *testing.T) { handler := stdhttp.HandlerFunc(func(w stdhttp.ResponseWriter, r *stdhttp.Request) { w.WriteHeader(204) }) var addr string if wrapped { srv := NewServer([]string{"127.0.0.1:0"}).UseHandler(handler). UseTCPOptions(TCPOptions{IdleTimeout: 2 * time.Second}). UseReadHeaderTimeout(100 * time.Millisecond).UseReadTimeout(2 * time.Second).UseWriteTimeout(2 * time.Second) serve, err := srv.Init(context.Background(), func(_ string, err error) { t.Error(err) }) if err != nil { t.Fatal(err) } addr = srv.listener.Addr().String() go serve() defer srv.Server.Close() } else { ln, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { t.Fatal(err) } srv := &stdhttp.Server{Handler: handler, ReadHeaderTimeout: 100 * time.Millisecond, ReadTimeout: 2 * time.Second, WriteTimeout: 2 * time.Second} addr = ln.Addr().String() go srv.Serve(ln) defer srv.Close() } conn, err := net.DialTimeout("tcp", addr, time.Second) if err != nil { t.Fatal(err) } defer conn.Close() conn.SetDeadline(time.Now().Add(3 * time.Second)) if _, err := io.WriteString(conn, "GET / HTTP/1.1\r\nHost: localhost\r\nX-Slow: "); err != nil { t.Fatal(err) } time.Sleep(400 * time.Millisecond) io.WriteString(conn, "done\r\nConnection: close\r\n\r\n") resp, err := stdhttp.ReadResponse(bufio.NewReader(conn), nil) if err != nil { t.Logf("request rejected after header timeout: %v", err) return } defer resp.Body.Close() t.Errorf("100ms request-header deadline accepted header completed after 400ms: HTTP %d", resp.StatusCode) }) } }