Factor flask.make_response() calls out into helper function

This commit is contained in:
Damien Elmes 2024-06-03 13:42:03 +07:00
parent bd88d15303
commit 5082d9ae5c

View File

@ -174,15 +174,24 @@ def _mime_for_path(path: str) -> str:
return mime or "application/octet-stream"
def _text_response(code: HTTPStatus, text: str) -> Response:
"""Return an error message.
Response is returned as text/plain, so no escaping of untrusted
input is required."""
resp = flask.make_response(text, code)
resp.headers["Content-type"] = "text/plain"
return resp
def _handle_local_file_request(request: LocalFileRequest) -> Response:
directory = request.root
path = request.path
try:
isdir = os.path.isdir(os.path.join(directory, path))
except ValueError:
return flask.make_response(
f"Path for '{directory} - {path}' is too long!",
HTTPStatus.BAD_REQUEST,
return _text_response(
HTTPStatus.BAD_REQUEST, f"Path for '{directory} - {path}' is too long!"
)
directory = os.path.realpath(directory)
@ -191,15 +200,14 @@ def _handle_local_file_request(request: LocalFileRequest) -> Response:
# protect against directory transversal: https://security.openstack.org/guidelines/dg_using-file-paths.html
if not fullpath.startswith(directory):
return flask.make_response(
f"Path for '{directory} - {path}' is a security leak!",
HTTPStatus.FORBIDDEN,
return _text_response(
HTTPStatus.FORBIDDEN, f"Path for '{directory} - {path}' is a security leak!"
)
if isdir:
return flask.make_response(
f"Path for '{directory} - {path}' is a directory (not supported)!",
return _text_response(
HTTPStatus.FORBIDDEN,
f"Path for '{directory} - {path}' is a directory (not supported)!",
)
try:
@ -219,10 +227,7 @@ def _handle_local_file_request(request: LocalFileRequest) -> Response:
)
else:
print(f"Not found: {path}")
return flask.make_response(
f"Invalid path: {path}",
HTTPStatus.NOT_FOUND,
)
return _text_response(HTTPStatus.NOT_FOUND, f"Invalid path: {path}")
except Exception as error:
if dev_mode:
@ -234,10 +239,7 @@ def _handle_local_file_request(request: LocalFileRequest) -> Response:
# swallow it - user likely surfed away from
# review screen before an image had finished
# downloading
return flask.make_response(
str(error),
HTTPStatus.INTERNAL_SERVER_ERROR,
)
return _text_response(HTTPStatus.INTERNAL_SERVER_ERROR, str(error))
def _builtin_data(path: str) -> bytes:
@ -270,10 +272,7 @@ def _handle_builtin_file_request(request: BundledFileRequest) -> Response:
except FileNotFoundError:
if dev_mode:
print(f"404: {data_path}")
resp = flask.make_response(
f"Invalid path: {path}",
HTTPStatus.NOT_FOUND,
)
resp = _text_response(HTTPStatus.NOT_FOUND, f"Invalid path: {path}")
# we're including the path verbatim in our response, so we need to either use
# plain text, or escape HTML characters to avoid reflecting untrusted input
resp.headers["Content-type"] = "text/plain"
@ -288,10 +287,7 @@ def _handle_builtin_file_request(request: BundledFileRequest) -> Response:
# swallow it - user likely surfed away from
# review screen before an image had finished
# downloading
return flask.make_response(
str(error),
HTTPStatus.INTERNAL_SERVER_ERROR,
)
return _text_response(HTTPStatus.INTERNAL_SERVER_ERROR, str(error))
@app.route("/<path:pathin>", methods=["GET", "POST"])
@ -310,10 +306,7 @@ def handle_request(pathin: str) -> Response:
if isinstance(req, NotFound):
print(req.message)
return flask.make_response(
f"Invalid path: {pathin}",
HTTPStatus.NOT_FOUND,
)
return _text_response(HTTPStatus.NOT_FOUND, f"Invalid path: {pathin}")
elif callable(req):
return _handle_dynamic_request(req)
elif isinstance(req, BundledFileRequest):
@ -321,10 +314,7 @@ def handle_request(pathin: str) -> Response:
elif isinstance(req, LocalFileRequest):
return _handle_local_file_request(req)
else:
return flask.make_response(
f"unexpected request: {pathin}",
HTTPStatus.FORBIDDEN,
)
return _text_response(HTTPStatus.FORBIDDEN, f"unexpected request: {pathin}")
def is_sveltekit_page(path: str) -> bool:
@ -665,12 +655,10 @@ def _extract_collection_post_request(path: str) -> DynamicRequest | NotFound:
response = flask.make_response(data)
response.headers["Content-Type"] = "application/binary"
else:
response = flask.make_response("", HTTPStatus.NO_CONTENT)
response = _text_response(HTTPStatus.NO_CONTENT, "")
except Exception as exc:
print(traceback.format_exc())
response = flask.make_response(
str(exc), HTTPStatus.INTERNAL_SERVER_ERROR
)
response = _text_response(HTTPStatus.INTERNAL_SERVER_ERROR, str(exc))
return response
return wrapped
@ -718,7 +706,7 @@ def _handle_dynamic_request(req: DynamicRequest) -> Response:
try:
return req()
except Exception as e:
return flask.make_response(str(e), HTTPStatus.INTERNAL_SERVER_ERROR)
return _text_response(HTTPStatus.INTERNAL_SERVER_ERROR, str(e))
def legacy_page_data() -> Response:
@ -726,7 +714,7 @@ def legacy_page_data() -> Response:
if html := aqt.mw.mediaServer.get_page_html(id):
return Response(html, mimetype="text/html")
else:
return flask.make_response("page not found", HTTPStatus.NOT_FOUND)
return _text_response(HTTPStatus.NOT_FOUND, "page not found")
def _extract_page_context() -> PageContext: