Skip to content
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
9 changes: 8 additions & 1 deletion py2http/default_configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,14 @@ def bottle_error_handler(error: Exception):


def flask_error_handler(error: Exception):
raise NotImplementedError()
"""The ``(body, status, headers)`` a Flask view returns for an error, mapped like
the bottle handler (``OPAQUE_ERRORS`` hides the text of a 500)."""
message = str(error)
status = error_status(error)
if status == 500 and os.getenv("OPAQUE_ERRORS", None):
message = "Internal server error"
status_line = f"400 {type(error).__name__}" if status == 400 else status
return {"error": message}, status_line, _status_headers(status)


def default_error_handler(error: Exception):
Expand Down
36 changes: 36 additions & 0 deletions py2http/tests/test_error_statuses.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,39 @@ def test_aiohttp_error_handler(error, status):
assert caught.value.status == status
if status == 500:
assert "internal detail" not in caught.value.text


@pytest.mark.parametrize("error, status", CASES)
def test_flask_error_handler(error, status, monkeypatch):
flask = pytest.importorskip("flask")
monkeypatch.delenv("PY2HTTP_WWW_AUTHENTICATE", raising=False)
monkeypatch.setenv("PY2HTTP_FRAMEWORK", "flask")
from py2http.default_configs import default_error_handler

app = flask.Flask(__name__)

@app.route("/fail")
def fail():
return default_error_handler(error)

response = app.test_client().get("/fail")
assert response.status_code == status
assert set(response.get_json()) == {"error"}
if status == 400: # as the bottle handler: the status line names the error
assert response.status == f"400 {type(error).__name__}"
if status == 401:
assert response.headers["WWW-Authenticate"] == "Bearer"
else:
assert "WWW-Authenticate" not in response.headers
if status == 500:
assert "internal detail" in response.get_json()["error"]


def test_flask_opaque_errors_hides_500_text(monkeypatch):
flask = pytest.importorskip("flask")
monkeypatch.setenv("OPAQUE_ERRORS", "1")
from py2http.default_configs import flask_error_handler

app = flask.Flask(__name__)
app.add_url_rule("/f", "f", lambda: flask_error_handler(KeyError("internal detail")))
assert app.test_client().get("/f").get_json() == {"error": "Internal server error"}
Loading