Skip to content

Catch exceptions from service handler and return internal error #77

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

Merged
merged 1 commit into from
Dec 5, 2024
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
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
Loading