Source file src/net/http/http1_server_test.go

     1  // Copyright 2026 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package http_test
     6  
     7  import (
     8  	"bufio"
     9  	"errors"
    10  	"internal/nettest"
    11  	"internal/synctest"
    12  	"io"
    13  	"net/http"
    14  	"net/http/httptest"
    15  	"strings"
    16  	"testing"
    17  )
    18  
    19  // An http1ServerTest tests an HTTP/1 server using a fake network.
    20  // It must be used in a synctest bubble.
    21  type http1ServerTest struct {
    22  	t  *testing.T
    23  	ts *httptest.Server
    24  }
    25  
    26  func newHTTP1ServerTest(t *testing.T, h http.HandlerFunc) *http1ServerTest {
    27  	if h == nil {
    28  		h = func(w http.ResponseWriter, req *http.Request) {}
    29  	}
    30  	st := &http1ServerTest{
    31  		t:  t,
    32  		ts: httptest.NewTestServer(t, h),
    33  	}
    34  	return st
    35  }
    36  
    37  // client returns a Client that sends requests to the server.
    38  func (st *http1ServerTest) client() *http.Client {
    39  	return st.ts.Client()
    40  }
    41  
    42  // transport returns a Transport that sends requests to the server.
    43  func (st *http1ServerTest) transport() *http.Transport {
    44  	return st.ts.Client().Transport.(*http.Transport)
    45  }
    46  
    47  // dial returns a connection to the server.
    48  func (st *http1ServerTest) dial() *http1TestConn {
    49  	t := st.t
    50  	t.Helper()
    51  	nc, err := st.transport().DialContext(st.t.Context(), "tcp", "example.tld")
    52  	if err != nil {
    53  		t.Fatal(err)
    54  	}
    55  	t.Cleanup(func() {
    56  		nc.Close()
    57  	})
    58  	conn := nc.(*nettest.Conn)
    59  	conn.SetReadError(errWouldBlock) // effectively make reads non-blocking
    60  	return &http1TestConn{
    61  		t:    st.t,
    62  		conn: conn,
    63  		bufr: bufio.NewReader(conn),
    64  	}
    65  }
    66  
    67  var errWouldBlock = errors.New("would block")
    68  
    69  type http1TestConn struct {
    70  	t    *testing.T
    71  	conn *nettest.Conn
    72  	bufr *bufio.Reader
    73  }
    74  
    75  // writeMessage writes a number of CRLF-terminated lines to the connection.
    76  func (tc *http1TestConn) writeMessage(lines ...string) {
    77  	t := tc.t
    78  	t.Helper()
    79  	if _, err := tc.conn.Write([]byte(strings.Join(lines, "\r\n") + "\r\n")); err != nil {
    80  		t.Fatalf("conn write: %v", err)
    81  	}
    82  }
    83  
    84  // readResponse reads a response from the connection (not including the response body).
    85  func (tc *http1TestConn) readResponse() *http.Response {
    86  	t := tc.t
    87  	t.Helper()
    88  	synctest.Wait()
    89  	resp, err := http.ReadResponse(tc.bufr, nil)
    90  	if err != nil {
    91  		t.Fatalf("ReadResponse: %v", err)
    92  	}
    93  	return resp
    94  }
    95  
    96  // wantIdle asserts that the connection is not closed and has no pending data to read.
    97  func (tc *http1TestConn) wantIdle() {
    98  	t := tc.t
    99  	t.Helper()
   100  	synctest.Wait()
   101  	if got, err := tc.bufr.Peek(32); len(got) != 0 || !errors.Is(err, errWouldBlock) {
   102  		t.Fatalf("read from conn: %q, %v; expect conn to be idle", got, err)
   103  	}
   104  }
   105  
   106  // wantClosed asserts that the connection is read-closed and has no pending data to read.
   107  func (tc *http1TestConn) wantClosed() {
   108  	t := tc.t
   109  	t.Helper()
   110  	synctest.Wait()
   111  	if got, err := tc.bufr.Peek(32); len(got) != 0 || err != io.EOF {
   112  		t.Fatalf("read from conn: %q; expect conn to be closed", got)
   113  	}
   114  }
   115  

View as plain text