8000 add an exception handler to serialize werkzeug HTTPException (#7790) · codeperl/localstack@e858045 · GitHub
[go: up one dir, main page]

Skip to content

Commit e858045

Browse files
authored
add an exception handler to serialize werkzeug HTTPException (localstack#7790)
1 parent f771a97 commit e858045

File tree

3 files changed

+86
-2
lines changed

3 files changed

+86
-2
lines changed

localstack/aws/handlers/fallback.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
22
import logging
33

44
from werkzeug.datastructures import Headers
5+
from werkzeug.exceptions import HTTPException
56

67
from localstack.http import Response
78

@@ -27,12 +28,18 @@ def __call__(
2728
# response already set
2829
return
2930

31+
if isinstance(exception, HTTPException):
32+
response.status_code = exception.code
33+
response.headers.update(exception.get_headers())
34+
response.set_json({"error": exception.name, "message": exception.description})
35+
return
36+
3037
LOG.debug("setting internal failure response for %s", exception)
3138
response.status_code = 500
3239
response.set_json(
3340
{
34-
"message": "Unexpected exception",
35-
"error": str(exception),
41+
"error": "Unexpected exception",
42+
"message": str(exception),
3643
"type": str(exception.__class__.__name__),
3744
}
3845
)

tests/integration/aws/__init__.py

Whitespace-only changes.

tests/integration/aws/test_app.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import pytest
2+
import requests
3+
from werkzeug.exceptions import Forbidden
4+
5+
from localstack.config import get_edge_url
6+
from localstack.services.edge import ROUTER
7+
8+
9+
class TestExceptionHandlers:
< 8000 code>10+
def test_internal_failure_handler_http_errors(self):
11+
response = requests.delete(get_edge_url() + "/_localstack/health")
12+
assert response.status_code == 405
13+
assert response.json() == {
14+
"error": "Method Not Allowed",
15+
"message": "The method is not allowed for the requested URL.",
16+
}
17+
assert "Allow" in response.headers
18+
19+
@pytest.mark.xfail(
20+
reason="fails until the service request parser stops detecting custom route requests as s3 requests"
21+
)
22+
def test_router_handler_get_http_errors(self, cleanups):
23+
def _raise_error(_request):
24+
raise Forbidden()
25+
26+
rule = ROUTER.add("/_raise_error", _raise_error)
27+
cleanups.append(lambda: ROUTER.remove(rule))
28+
29+
response = requests.get(get_edge_url() + "/_raise_error")
30+
assert response.status_code == 403
31+
assert response.json() == {
32+
"error": "Forbidden",
33+
"message": "You don't have the permission to access the requested resource. It is "
34+
"either read-protected or not readable by the server.",
35+
}
36+
37+
def test_router_handler_patch_http_errors(self, cleanups):
38+
# this one works because PATCH operations are not detected by the service name parser as s3 requestss
39+
def _raise_error(_request):
40+
raise Forbidden()
41+
42+
rule = ROUTER.add("/_raise_error", _raise_error, methods=["PATCH"])
43+
cleanups.append(lambda: ROUTER.remove(rule))
44+
45+
response = requests.patch(get_edge_url() + "/_raise_error")
46+
assert response.status_code == 403
47+
assert response.json() == {
48+
"error": "Forbidden",
49+
"message": "You don't have the permission to access the requested resource. It is "
50+
"either read-protected or not readable by the server.",
51+
}
52+
53+
@pytest.mark.xfail(
54+
reason="fails until the service request parser stops detecting custom route requests as s3 requests"
55+
)
56+
def test_router_handler_get_unexpected_errors(self, cleanups):
57+
def _raise_error(_request):
58+
raise ValueError("oh noes (this is expected)")
59+
60+
rule = ROUTER.add("/_raise_error", _raise_error)
61+
cleanups.append(lambda: ROUTER.remove(rule))
62+
63+
response = requests.get(get_edge_url() + "/_raise_error")
64+
assert response.status_code == 500
65+
assert response.json() == {
66+
"error": "Unexpected exception",
67+
"message": "oh noes (this is expected)",
68+
"type": "ValueError",
69+
}
70+
71+
def test_404_unfortunately_detected_as_s3_request(self):
72+
# FIXME: this is because unknown routes have to be interpreted as s3 requests
73+
response = requests.get(get_edge_url() + "/_raise_error")
74+
assert response.status_code == 404
75+
assert response.text.startswith(
76+
'<?xml version="1.0" encoding="UTF-8"?>\n<Error><Code>NoSuchBucket</Code>'
77+
)

0 commit comments

Comments
 (0)
0