Skip to content

Commit

Permalink
Merge pull request #77 from bgreni/catch-handler-exceptions
Browse files Browse the repository at this point in the history
Catch exceptions from service handler and return internal error
  • Loading branch information
bgreni authored Dec 5, 2024
2 parents bd58e0d + 2181258 commit ea897f7
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 11 deletions.
10 changes: 10 additions & 0 deletions integration_test_client.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,32 @@ struct IntegrationTest:
self.client = Client()

fn test_redirect(inout self) raises:
print("Testing redirect...")
var h = Headers(Header(HeaderKey.CONNECTION, 'keep-alive'))
var res = self.client.do(HTTPRequest(u("redirect"), headers=h))
assert_equal(res.status_code, StatusCode.OK)
assert_equal(to_string(res.body_raw), "yay you made it")
assert_equal(res.headers[HeaderKey.CONNECTION], "keep-alive")

fn test_close_connection(inout self) raises:
print("Testing close connection...")
var h = Headers(Header(HeaderKey.CONNECTION, 'close'))
var res = self.client.do(HTTPRequest(u("close-connection"), headers=h))
assert_equal(res.status_code, StatusCode.OK)
assert_equal(to_string(res.body_raw), "connection closed")
assert_equal(res.headers[HeaderKey.CONNECTION], "close")

fn test_server_error(inout self) raises:
print("Testing internal server error...")
var res = self.client.do(HTTPRequest(u("error")))
assert_equal(res.status_code, StatusCode.INTERNAL_ERROR)
assert_equal(res.status_text, "Internal Server Error")


fn run_tests(inout self) raises:
self.test_redirect()
self.test_close_connection()
self.test_server_error()

fn main() raises:
var test = IntegrationTest()
Expand Down
7 changes: 5 additions & 2 deletions integration_test_server.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ from lightbug_http import *

@value
struct IntegerationTestService(HTTPService):
fn func(self, req: HTTPRequest) raises -> HTTPResponse:
fn func(inout self, req: HTTPRequest) raises -> HTTPResponse:
var p = req.uri.path
if p == "/redirect":
return HTTPResponse(
Expand All @@ -16,10 +16,13 @@ struct IntegerationTestService(HTTPService):
return OK("yay you made it")
elif p == "/close-connection":
return OK("connection closed")
elif p == "/error":
raise Error("oops")

return NotFound("wrong")

fn main() raises:
var server = Server(tcp_keep_alive=True)
server.listen_and_serve("127.0.0.1:8080", IntegerationTestService())
var service = IntegerationTestService()
server.listen_and_serve("127.0.0.1:8080", service)

2 changes: 1 addition & 1 deletion lightbug_http/cookie/expiration.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,5 @@ struct Expiration(CollectionElement):
elif not bool(self.datetime) and not bool(other.datetime):
return True
return self.datetime.value().isoformat() == other.datetime.value().isoformat()

return True
9 changes: 9 additions & 0 deletions lightbug_http/http/common_response.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,12 @@ fn NotFound(path: String) -> HTTPResponse:
headers=Headers(Header(HeaderKey.CONTENT_TYPE, "text/plain")),
body_bytes=bytes("path " + path + " not found"),
)


fn InternalError() -> HTTPResponse:
return HTTPResponse(
bytes("Failed to process request"),
status_code=500,
headers=Headers(Header(HeaderKey.CONTENT_TYPE, "text/plain")),
status_text="Internal Server Error",
)
1 change: 1 addition & 0 deletions lightbug_http/http/response.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ struct StatusCode:
alias TEMPORARY_REDIRECT = 307
alias PERMANENT_REDIRECT = 308
alias NOT_FOUND = 404
alias INTERNAL_ERROR = 500


@value
Expand Down
6 changes: 3 additions & 3 deletions lightbug_http/net.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ struct ListenConfig:
fn __init__(inout self) raises:
self.__keep_alive = default_tcp_keep_alive

fn __init__(inout self, keep_alive: Duration) raises:
fn __init__(inout self, keep_alive: Duration):
self.__keep_alive = keep_alive

fn listen(inout self, network: String, address: String) raises -> NoTLSListener:
Expand Down Expand Up @@ -272,10 +272,10 @@ struct SysConnection(Connection):
struct SysNet:
var __lc: ListenConfig

fn __init__(inout self) raises:
fn __init__(inout self):
self.__lc = ListenConfig(default_tcp_keep_alive)

fn __init__(inout self, keep_alive: Duration) raises:
fn __init__(inout self, keep_alive: Duration):
self.__lc = ListenConfig(keep_alive)

fn listen(inout self, network: String, addr: String) raises -> NoTLSListener:
Expand Down
17 changes: 12 additions & 5 deletions lightbug_http/server.mojo
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ from lightbug_http.strings import NetworkType
from lightbug_http.utils import ByteReader
from lightbug_http.net import NoTLSListener, default_buffer_size, NoTLSListener, SysConnection, SysNet
from lightbug_http.http import HTTPRequest, encode
from lightbug_http.http.common_response import InternalError
from lightbug_http.uri import URI
from lightbug_http.header import Headers
from lightbug_http.service import HTTPService
Expand Down Expand Up @@ -119,7 +120,7 @@ struct Server:
concurrency = DefaultConcurrency
return concurrency

fn listen_and_serve[T: HTTPService](inout self, address: String, inout handler: T) raises -> None:
fn listen_and_serve[T: HTTPService](inout self, address: String, inout handler: T) raises:
"""
Listen for incoming connections and serve HTTP requests.
Expand All @@ -132,7 +133,7 @@ struct Server:
_ = self.set_address(address)
self.serve(listener, handler)

fn serve[T: HTTPService](inout self, ln: NoTLSListener, inout handler: T) raises -> None:
fn serve[T: HTTPService](inout self, ln: NoTLSListener, inout handler: T) raises:
"""
Serve HTTP requests.
Expand All @@ -141,7 +142,7 @@ struct Server:
handler : HTTPService - An object that handles incoming HTTP requests.
Raises:
If there is an error while serving requests.
If there is an error while serving requests.
"""
self.ln = ln

Expand All @@ -158,7 +159,7 @@ struct Server:
handler : HTTPService - An object that handles incoming HTTP requests.
Raises:
If there is an error while serving the connection.
If there is an error while serving the connection.
"""
var max_request_body_size = self.max_request_body_size()
if max_request_body_size <= 0:
Expand All @@ -177,7 +178,13 @@ struct Server:

var request = HTTPRequest.from_bytes(self.address(), max_request_body_size, b^)

var res = handler.func(request)
var res: HTTPResponse
try:
res = handler.func(request)
except:
_ = conn.write(encode(InternalError()))
conn.close()
return

var close_connection = (not self.tcp_keep_alive) or request.connection_close()

Expand Down

0 comments on commit ea897f7

Please sign in to comment.