diff --git a/integration_test_client.mojo b/integration_test_client.mojo index d5c5aa65..5b465e87 100644 --- a/integration_test_client.mojo +++ b/integration_test_client.mojo @@ -12,6 +12,7 @@ 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) @@ -19,15 +20,24 @@ struct IntegrationTest: 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() diff --git a/integration_test_server.mojo b/integration_test_server.mojo index 84e2e4e5..569a9440 100644 --- a/integration_test_server.mojo +++ b/integration_test_server.mojo @@ -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( @@ -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) \ No newline at end of file diff --git a/lightbug_http/cookie/expiration.mojo b/lightbug_http/cookie/expiration.mojo index bc13d74f..5a94bd2e 100644 --- a/lightbug_http/cookie/expiration.mojo +++ b/lightbug_http/cookie/expiration.mojo @@ -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 diff --git a/lightbug_http/http/common_response.mojo b/lightbug_http/http/common_response.mojo index 65b09888..75d5018a 100644 --- a/lightbug_http/http/common_response.mojo +++ b/lightbug_http/http/common_response.mojo @@ -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", + ) diff --git a/lightbug_http/http/response.mojo b/lightbug_http/http/response.mojo index 8f32c380..586e3264 100644 --- a/lightbug_http/http/response.mojo +++ b/lightbug_http/http/response.mojo @@ -24,6 +24,7 @@ struct StatusCode: alias TEMPORARY_REDIRECT = 307 alias PERMANENT_REDIRECT = 308 alias NOT_FOUND = 404 + alias INTERNAL_ERROR = 500 @value diff --git a/lightbug_http/net.mojo b/lightbug_http/net.mojo index eac87e94..8b351792 100644 --- a/lightbug_http/net.mojo +++ b/lightbug_http/net.mojo @@ -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: @@ -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: diff --git a/lightbug_http/server.mojo b/lightbug_http/server.mojo index e1c95efa..4ff5b40c 100644 --- a/lightbug_http/server.mojo +++ b/lightbug_http/server.mojo @@ -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 @@ -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. @@ -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. @@ -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 @@ -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: @@ -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()