Skip to content

Commit

Permalink
Merge pull request #40 from saviorand/fix/http11-conn-close
Browse files Browse the repository at this point in the history
Adhere to HTTP 1.1 spec, keep conn open by default
  • Loading branch information
saviorand authored May 20, 2024
2 parents f3ba39b + 05df473 commit bd2f4ef
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 40 deletions.
4 changes: 2 additions & 2 deletions lightbug_http/header.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -214,10 +214,9 @@ struct RequestHeader:
fn headers(self) -> String:
return String(self.raw_headers)

# This is translated to Mojo from Golang FastHTTP
fn parse(inout self, request_line: String) raises -> None:
var headers = self.raw_headers

var n = request_line.find(" ")
if n <= 0:
raise Error("Cannot find HTTP request method in the request")
Expand Down Expand Up @@ -254,6 +253,7 @@ struct RequestHeader:
s.disable_normalization = self.disable_normalization

while s.next():
# The below is based on the code from Golang's FastHTTP library
if len(s.key) > 0:
# Spaces between the header key and colon are not allowed.
# See RFC 7230, Section 3.2.4.
Expand Down
3 changes: 3 additions & 0 deletions lightbug_http/python/server.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ struct PythonServer:
var conn = self.ln.accept()
var buf = Bytes()
var read_len = conn.read(buf)
if read_len == 0:
conn.close()
break
var first_line_and_headers = next_line(buf)
var request_line = first_line_and_headers.first_line
var rest_of_headers = first_line_and_headers.rest
Expand Down
3 changes: 3 additions & 0 deletions lightbug_http/sys/net.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,9 @@ struct SysConnection(Connection):
var bytes_recv = recv(self.fd, new_buf, default_buffer_size, 0)
if bytes_recv == -1:
print("Failed to receive message")
return 0
if bytes_recv == 0:
return 0
var bytes_str = String(new_buf.bitcast[Int8](), bytes_recv)
buf = bytes_str._buffer
return bytes_recv
Expand Down
81 changes: 43 additions & 38 deletions lightbug_http/sys/server.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -83,48 +83,53 @@ struct SysServer:
Raises:
If there is an error while serving requests.
"""
# var max_worker_count = self.get_concurrency()
# TODO: logic for non-blocking read and write here, see for example https://github.com/valyala/fasthttp/blob/9ba16466dfd5d83e2e6a005576ee0d8e127457e2/server.go#L1789

self.ln = ln

while True:
var conn = self.ln.accept()
var buf = Bytes()
var read_len = conn.read(buf)
var request = next_line(buf)
var headers_and_body = next_line(request.rest, "\n\n")
var request_headers = headers_and_body.first_line
var request_body = headers_and_body.rest
var uri = URI(request.first_line)
try:
uri.parse()
except e:
conn.close()
raise Error("Failed to parse request line:" + e.__str__())

var header = RequestHeader(request_headers._buffer)
try:
header.parse(request.first_line)
except e:
conn.close()
raise Error("Failed to parse request header: " + e.__str__())

if header.content_length() != 0 and header.content_length() != (len(request_body) + 1):
var remaining_body = Bytes()
var remaining_len = header.content_length() - len(request_body + 1)
while remaining_len > 0:
var read_len = conn.read(remaining_body)
buf.extend(remaining_body)
remaining_len -= read_len

var res = handler.func(
HTTPRequest(
uri,
buf,
header,
while True:
var read_len = conn.read(buf)
if read_len == 0:
conn.close()
break
var request = next_line(buf)
var headers_and_body = next_line(request.rest, "\n\n")
var request_headers = headers_and_body.first_line
var request_body = headers_and_body.rest
var uri = URI(request.first_line)
try:
uri.parse()
except e:
conn.close()
raise Error("Failed to parse request line:" + e.__str__())

var header = RequestHeader(request_headers._buffer)
try:
header.parse(request.first_line)
except e:
conn.close()
raise Error("Failed to parse request header: " + e.__str__())

if header.content_length() != 0 and header.content_length() != (len(request_body) + 1):
var remaining_body = Bytes()
var remaining_len = header.content_length() - len(request_body + 1)
while remaining_len > 0:
var read_len = conn.read(remaining_body)
buf.extend(remaining_body)
remaining_len -= read_len

var res = handler.func(
HTTPRequest(
uri,
buf,
header,
)
)
)
var res_encoded = encode(res)
_ = conn.write(res_encoded)
conn.close()
var res_encoded = encode(res)
_ = conn.write(res_encoded)

if header.connection_close():
conn.close()
break

0 comments on commit bd2f4ef

Please sign in to comment.