Skip to content

Commit ea897f7

Browse files
authored
Merge pull request #77 from bgreni/catch-handler-exceptions
Catch exceptions from service handler and return internal error
2 parents bd58e0d + 2181258 commit ea897f7

File tree

7 files changed

+41
-11
lines changed

7 files changed

+41
-11
lines changed

integration_test_client.mojo

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,32 @@ struct IntegrationTest:
1212
self.client = Client()
1313

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

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

30+
fn test_server_error(inout self) raises:
31+
print("Testing internal server error...")
32+
var res = self.client.do(HTTPRequest(u("error")))
33+
assert_equal(res.status_code, StatusCode.INTERNAL_ERROR)
34+
assert_equal(res.status_text, "Internal Server Error")
35+
36+
2837
fn run_tests(inout self) raises:
2938
self.test_redirect()
3039
self.test_close_connection()
40+
self.test_server_error()
3141

3242
fn main() raises:
3343
var test = IntegrationTest()

integration_test_server.mojo

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ from lightbug_http import *
22

33
@value
44
struct IntegerationTestService(HTTPService):
5-
fn func(self, req: HTTPRequest) raises -> HTTPResponse:
5+
fn func(inout self, req: HTTPRequest) raises -> HTTPResponse:
66
var p = req.uri.path
77
if p == "/redirect":
88
return HTTPResponse(
@@ -16,10 +16,13 @@ struct IntegerationTestService(HTTPService):
1616
return OK("yay you made it")
1717
elif p == "/close-connection":
1818
return OK("connection closed")
19+
elif p == "/error":
20+
raise Error("oops")
1921

2022
return NotFound("wrong")
2123

2224
fn main() raises:
2325
var server = Server(tcp_keep_alive=True)
24-
server.listen_and_serve("127.0.0.1:8080", IntegerationTestService())
26+
var service = IntegerationTestService()
27+
server.listen_and_serve("127.0.0.1:8080", service)
2528

lightbug_http/cookie/expiration.mojo

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,5 @@ struct Expiration(CollectionElement):
5252
elif not bool(self.datetime) and not bool(other.datetime):
5353
return True
5454
return self.datetime.value().isoformat() == other.datetime.value().isoformat()
55-
55+
5656
return True

lightbug_http/http/common_response.mojo

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,12 @@ fn NotFound(path: String) -> HTTPResponse:
4343
headers=Headers(Header(HeaderKey.CONTENT_TYPE, "text/plain")),
4444
body_bytes=bytes("path " + path + " not found"),
4545
)
46+
47+
48+
fn InternalError() -> HTTPResponse:
49+
return HTTPResponse(
50+
bytes("Failed to process request"),
51+
status_code=500,
52+
headers=Headers(Header(HeaderKey.CONTENT_TYPE, "text/plain")),
53+
status_text="Internal Server Error",
54+
)

lightbug_http/http/response.mojo

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ struct StatusCode:
2424
alias TEMPORARY_REDIRECT = 307
2525
alias PERMANENT_REDIRECT = 308
2626
alias NOT_FOUND = 404
27+
alias INTERNAL_ERROR = 500
2728

2829

2930
@value

lightbug_http/net.mojo

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ struct ListenConfig:
146146
fn __init__(inout self) raises:
147147
self.__keep_alive = default_tcp_keep_alive
148148

149-
fn __init__(inout self, keep_alive: Duration) raises:
149+
fn __init__(inout self, keep_alive: Duration):
150150
self.__keep_alive = keep_alive
151151

152152
fn listen(inout self, network: String, address: String) raises -> NoTLSListener:
@@ -272,10 +272,10 @@ struct SysConnection(Connection):
272272
struct SysNet:
273273
var __lc: ListenConfig
274274

275-
fn __init__(inout self) raises:
275+
fn __init__(inout self):
276276
self.__lc = ListenConfig(default_tcp_keep_alive)
277277

278-
fn __init__(inout self, keep_alive: Duration) raises:
278+
fn __init__(inout self, keep_alive: Duration):
279279
self.__lc = ListenConfig(keep_alive)
280280

281281
fn listen(inout self, network: String, addr: String) raises -> NoTLSListener:

lightbug_http/server.mojo

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ from lightbug_http.strings import NetworkType
44
from lightbug_http.utils import ByteReader
55
from lightbug_http.net import NoTLSListener, default_buffer_size, NoTLSListener, SysConnection, SysNet
66
from lightbug_http.http import HTTPRequest, encode
7+
from lightbug_http.http.common_response import InternalError
78
from lightbug_http.uri import URI
89
from lightbug_http.header import Headers
910
from lightbug_http.service import HTTPService
@@ -119,7 +120,7 @@ struct Server:
119120
concurrency = DefaultConcurrency
120121
return concurrency
121122

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

135-
fn serve[T: HTTPService](inout self, ln: NoTLSListener, inout handler: T) raises -> None:
136+
fn serve[T: HTTPService](inout self, ln: NoTLSListener, inout handler: T) raises:
136137
"""
137138
Serve HTTP requests.
138139
@@ -141,7 +142,7 @@ struct Server:
141142
handler : HTTPService - An object that handles incoming HTTP requests.
142143
143144
Raises:
144-
If there is an error while serving requests.
145+
If there is an error while serving requests.
145146
"""
146147
self.ln = ln
147148

@@ -158,7 +159,7 @@ struct Server:
158159
handler : HTTPService - An object that handles incoming HTTP requests.
159160
160161
Raises:
161-
If there is an error while serving the connection.
162+
If there is an error while serving the connection.
162163
"""
163164
var max_request_body_size = self.max_request_body_size()
164165
if max_request_body_size <= 0:
@@ -177,7 +178,13 @@ struct Server:
177178

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

180-
var res = handler.func(request)
181+
var res: HTTPResponse
182+
try:
183+
res = handler.func(request)
184+
except:
185+
_ = conn.write(encode(InternalError()))
186+
conn.close()
187+
return
181188

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

0 commit comments

Comments
 (0)