authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-02-21 00:44:51-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-02-23 02:37:11-07:00
log2e7d8062cad12510c37bf1b882058c8fc869b6c0
tree5d8aab46c64acfda8175b9e3cde8018616612563
parentb4b9f6aa4a5bfd6a54b59444f3e1a3706358eb76

std.http.Server: fix seeing phantom request


1 files changed, 19 insertions(+), 3 deletions(-)

lib/std/http/Server.zig+19-3
...@@ -31,7 +31,7 @@ pub const State = enum {...@@ -31,7 +31,7 @@ pub const State = enum {
3131
32/// Initialize an HTTP server that can respond to multiple requests on the same32/// Initialize an HTTP server that can respond to multiple requests on the same
33/// connection.33/// connection.
34/// The returned `Server` is ready for `readRequest` to be called.34/// The returned `Server` is ready for `receiveHead` to be called.
35pub fn init(connection: net.Server.Connection, read_buffer: []u8) Server {35pub fn init(connection: net.Server.Connection, read_buffer: []u8) Server {
36 return .{36 return .{
37 .connection = connection,37 .connection = connection,
...@@ -51,6 +51,12 @@ pub const ReceiveHeadError = error{...@@ -51,6 +51,12 @@ pub const ReceiveHeadError = error{
51 HttpHeadersInvalid,51 HttpHeadersInvalid,
52 /// A low level I/O error occurred trying to read the headers.52 /// A low level I/O error occurred trying to read the headers.
53 HttpHeadersUnreadable,53 HttpHeadersUnreadable,
54 /// Partial HTTP request was received but the connection was closed before
55 /// fully receiving the headers.
56 HttpRequestTruncated,
57 /// The client sent 0 bytes of headers before closing the stream.
58 /// In other words, a keep-alive connection was finally closed.
59 HttpConnectionClosing,
54};60};
5561
56/// The header bytes reference the read buffer that Server was initialized with62/// The header bytes reference the read buffer that Server was initialized with
...@@ -63,8 +69,11 @@ pub fn receiveHead(s: *Server) ReceiveHeadError!Request {...@@ -63,8 +69,11 @@ pub fn receiveHead(s: *Server) ReceiveHeadError!Request {
63 // In case of a reused connection, move the next request's bytes to the69 // In case of a reused connection, move the next request's bytes to the
64 // beginning of the buffer.70 // beginning of the buffer.
65 if (s.next_request_start > 0) {71 if (s.next_request_start > 0) {
66 if (s.read_buffer_len > s.next_request_start) rebase(s, 0);72 if (s.read_buffer_len > s.next_request_start) {
67 s.next_request_start = 0;73 rebase(s, 0);
74 } else {
75 s.read_buffer_len = 0;
76 }
68 }77 }
6978
70 var hp: http.HeadParser = .{};79 var hp: http.HeadParser = .{};
...@@ -82,6 +91,13 @@ pub fn receiveHead(s: *Server) ReceiveHeadError!Request {...@@ -82,6 +91,13 @@ pub fn receiveHead(s: *Server) ReceiveHeadError!Request {
82 return error.HttpHeadersOversize;91 return error.HttpHeadersOversize;
83 const read_n = s.connection.stream.read(buf) catch92 const read_n = s.connection.stream.read(buf) catch
84 return error.HttpHeadersUnreadable;93 return error.HttpHeadersUnreadable;
94 if (read_n == 0) {
95 if (s.read_buffer_len > 0) {
96 return error.HttpRequestTruncated;
97 } else {
98 return error.HttpConnectionClosing;
99 }
100 }
85 s.read_buffer_len += read_n;101 s.read_buffer_len += read_n;
86 const bytes = buf[0..read_n];102 const bytes = buf[0..read_n];
87 const end = hp.feed(bytes);103 const end = hp.feed(bytes);