feat: stream native request bodies
This commit is contained in:
@@ -107,6 +107,47 @@ func TestServerRejectsMalformedBodyAndLimits(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerStreamsContentLengthBodyToHandler(t *testing.T) {
|
||||
entered := make(chan struct{})
|
||||
application := omni.NewWithRouter(netrouter.New())
|
||||
application.POST("/body", func(ctx *omni.Context) error {
|
||||
close(entered)
|
||||
body, err := io.ReadAll(ctx.Request().Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ctx.OK(map[string]string{"body": string(body)})
|
||||
})
|
||||
server, listener, done := startServer(t, application)
|
||||
defer stopServer(t, server, listener, done)
|
||||
|
||||
conn, err := net.Dial("tcp", listener.Addr().String())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer conn.Close()
|
||||
if _, err := io.WriteString(conn, "POST /body HTTP/1.1\r\nHost: test\r\nContent-Length: 5\r\n\r\nhel"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
select {
|
||||
case <-entered:
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("handler did not start before the complete body arrived")
|
||||
}
|
||||
if _, err := io.WriteString(conn, "lo"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
response, err := http.ReadResponse(bufio.NewReader(conn), &http.Request{Method: http.MethodPost})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
body, err := io.ReadAll(response.Body)
|
||||
response.Body.Close()
|
||||
if err != nil || response.StatusCode != http.StatusOK || !strings.Contains(string(body), `"body":"hello"`) {
|
||||
t.Fatalf("unexpected streamed body response: status=%d body=%s error=%v", response.StatusCode, body, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerChunkedBodyAndTrailers(t *testing.T) {
|
||||
application := omni.NewWithRouter(netrouter.New())
|
||||
application.POST("/body", func(ctx *omni.Context) error {
|
||||
@@ -154,11 +195,18 @@ func TestServerChunkedBodyLimit(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestServerSlowBodyTimesOutBeforeHandler(t *testing.T) {
|
||||
func TestServerSlowBodyTimesOutWithoutSuccessfulHandler(t *testing.T) {
|
||||
var handlerCalls atomic.Int32
|
||||
application := omni.NewWithRouter(netrouter.New())
|
||||
application.POST("/body", func(ctx *omni.Context) error {
|
||||
body, err := io.ReadAll(ctx.Request().Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
handlerCalls.Add(1)
|
||||
if len(body) != 4 {
|
||||
return fmt.Errorf("unexpected body length %d", len(body))
|
||||
}
|
||||
return ctx.OK("ok")
|
||||
})
|
||||
server := native.New(application)
|
||||
@@ -178,14 +226,10 @@ func TestServerSlowBodyTimesOutBeforeHandler(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer conn.Close()
|
||||
conn.SetReadDeadline(time.Now().Add(time.Second))
|
||||
_, _ = io.WriteString(conn, "POST /body HTTP/1.1\r\nHost: test\r\nContent-Length: 4\r\n\r\na")
|
||||
buffer := make([]byte, 1)
|
||||
if _, err := conn.Read(buffer); err == nil {
|
||||
t.Fatal("expected slow request body to time out and close")
|
||||
}
|
||||
requirePeerClose(t, conn)
|
||||
if handlerCalls.Load() != 0 {
|
||||
t.Fatal("handler ran before the request body was complete")
|
||||
t.Fatal("handler reported success before the request body was complete")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user