Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix reader not skipping over all CRLF #241

Merged
merged 4 commits into from
Feb 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 12 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,25 +97,22 @@ Once you have a Mojo project set up locally,
For example, to make a `Printer` service that prints some details about the request to console:

```mojo
from lightbug_http import *
from lightbug_http.http import HTTPRequest, HTTPResponse, OK
from lightbug_http.strings import to_string
from lightbug_http.header import HeaderKey

@value
struct Printer(HTTPService):
fn func(mut self, req: HTTPRequest) raises -> HTTPResponse:
var uri = req.uri
print("Request URI: ", to_string(uri.request_uri))

var header = req.headers
print("Request protocol: ", req.protocol)
print("Request method: ", req.method)
print(
"Request Content-Type: ", to_string(header[HeaderKey.CONTENT_TYPE])
)

var body = req.body_raw
print("Request Body: ", to_string(body))

return OK(body)
print("Request URI:", req.uri.request_uri)
print("Request protocol:", req.protocol)
print("Request method:", req.method)
if HeaderKey.CONTENT_TYPE in req.headers:
print("Request Content-Type:", req.headers[HeaderKey.CONTENT_TYPE])
if req.body_raw:
print("Request Body:", to_string(req.body_raw))

saviorand marked this conversation as resolved.
Show resolved Hide resolved
return OK(req.body_raw)
```

6. Start a server listening on a port with your service like so.
Expand Down
11 changes: 7 additions & 4 deletions lightbug_http/http/request.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,13 @@ struct HTTPRequest(Writable, Stringable):
var request = HTTPRequest(
URI.parse(addr + uri), headers=headers, method=method, protocol=protocol, cookies=cookies
)
try:
request.read_body(reader, content_length, max_body_size)
except e:
raise Error("HTTPRequest.from_bytes: Failed to read request body: " + str(e))

if content_length > 0:
try:
reader.skip_carriage_return()
request.read_body(reader, content_length, max_body_size)
except e:
raise Error("HTTPRequest.from_bytes: Failed to read request body: " + str(e))

return request

Expand Down
5 changes: 3 additions & 2 deletions lightbug_http/server.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -161,14 +161,15 @@ struct Server(Movable):
var response: HTTPResponse
try:
response = handler.func(request)
except:
except e:
logger.error("Unexpected error in the handler:", e)

if not conn.is_closed():
# Try to send back an internal server error, but always attempt to teardown the connection.
saviorand marked this conversation as resolved.
Show resolved Hide resolved
try:
# TODO: Move InternalError response to an alias when Mojo can support Dict operations at compile time. (@thatstoasty)
_ = conn.write(encode(InternalError()))
except e:
logger.error(e)
raise Error("Failed to send InternalError response")
finally:
conn.teardown()
Expand Down
6 changes: 4 additions & 2 deletions lightbug_http/service.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ struct Printer(HTTPService):
print("Request URI:", req.uri.request_uri)
print("Request protocol:", req.protocol)
print("Request method:", req.method)
print("Request Content-Type:", req.headers[HeaderKey.CONTENT_TYPE])
print("Request Body:", to_string(req.body_raw))
if HeaderKey.CONTENT_TYPE in req.headers:
print("Request Content-Type:", req.headers[HeaderKey.CONTENT_TYPE])
if req.body_raw:
print("Request Body:", to_string(req.body_raw))

return OK(req.body_raw)

Expand Down
10 changes: 9 additions & 1 deletion tests/lightbug_http/http/test_request.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,15 @@ def test_request_from_bytes():


def test_read_body():
...
alias data = "GET /redirect HTTP/1.1\r\nHost: 127.0.0.1:8080\r\nUser-Agent: python-requests/2.32.3\r\nAccept-Encoding: gzip, deflate, br, zstd\r\nAccept: */\r\nContent-Length: 17\r\nconnection: keep-alive\r\n\r\nThis is the body!"
var request = HTTPRequest.from_bytes("127.0.0.1", 4096, data.as_bytes())
testing.assert_equal(request.protocol, "HTTP/1.1")
testing.assert_equal(request.method, "GET")
testing.assert_equal(request.uri.request_uri, "/redirect")
testing.assert_equal(request.headers["Host"], "127.0.0.1:8080")
testing.assert_equal(request.headers["User-Agent"], "python-requests/2.32.3")

testing.assert_equal(request.get_body(), "This is the body!")


def test_encode():
Expand Down