mirror of
https://gitlab.archlinux.org/archlinux/aurweb.git
synced 2025-02-03 10:43:03 +01:00
change(fastapi): centralize HTTPException
Signed-off-by: Kevin Morris <kevr@0cost.org>
This commit is contained in:
parent
a747548254
commit
abfd41f31e
6 changed files with 28 additions and 51 deletions
|
@ -6,8 +6,8 @@ import typing
|
||||||
|
|
||||||
from urllib.parse import quote_plus
|
from urllib.parse import quote_plus
|
||||||
|
|
||||||
from fastapi import FastAPI, HTTPException, Request
|
from fastapi import FastAPI, HTTPException, Request, Response
|
||||||
from fastapi.responses import HTMLResponse, RedirectResponse
|
from fastapi.responses import RedirectResponse
|
||||||
from fastapi.staticfiles import StaticFiles
|
from fastapi.staticfiles import StaticFiles
|
||||||
from prometheus_client import multiprocess
|
from prometheus_client import multiprocess
|
||||||
from sqlalchemy import and_, or_
|
from sqlalchemy import and_, or_
|
||||||
|
@ -21,10 +21,11 @@ from aurweb.auth import BasicAuthBackend
|
||||||
from aurweb.db import get_engine, query
|
from aurweb.db import get_engine, query
|
||||||
from aurweb.models import AcceptedTerm, Term
|
from aurweb.models import AcceptedTerm, Term
|
||||||
from aurweb.prometheus import http_api_requests_total, http_requests_total, instrumentator
|
from aurweb.prometheus import http_api_requests_total, http_requests_total, instrumentator
|
||||||
from aurweb.routers import accounts, auth, errors, html, packages, rpc, rss, sso, trusted_user
|
from aurweb.routers import accounts, auth, html, packages, rpc, rss, sso, trusted_user
|
||||||
|
from aurweb.templates import make_context, render_template
|
||||||
|
|
||||||
# Setup the FastAPI app.
|
# Setup the FastAPI app.
|
||||||
app = FastAPI(exception_handlers=errors.exceptions)
|
app = FastAPI()
|
||||||
|
|
||||||
# Instrument routes with the prometheus-fastapi-instrumentator
|
# Instrument routes with the prometheus-fastapi-instrumentator
|
||||||
# library with custom collectors and expose /metrics.
|
# library with custom collectors and expose /metrics.
|
||||||
|
@ -93,14 +94,15 @@ def child_exit(server, worker): # pragma: no cover
|
||||||
|
|
||||||
|
|
||||||
@app.exception_handler(HTTPException)
|
@app.exception_handler(HTTPException)
|
||||||
async def http_exception_handler(request, exc):
|
async def http_exception_handler(request: Request, exc: HTTPException) \
|
||||||
"""
|
-> Response:
|
||||||
Dirty HTML error page to replace the default JSON error responses.
|
""" Handle an HTTPException thrown in a route. """
|
||||||
In the future this should use a proper Arch-themed HTML template.
|
|
||||||
"""
|
|
||||||
phrase = http.HTTPStatus(exc.status_code).phrase
|
phrase = http.HTTPStatus(exc.status_code).phrase
|
||||||
return HTMLResponse(f"<h1>{exc.status_code} {phrase}</h1><p>{exc.detail}</p>",
|
context = make_context(request, phrase)
|
||||||
status_code=exc.status_code)
|
context["exc"] = exc
|
||||||
|
context["phrase"] = phrase
|
||||||
|
return render_template(request, "errors/detail.html", context,
|
||||||
|
exc.status_code)
|
||||||
|
|
||||||
|
|
||||||
@app.middleware("http")
|
@app.middleware("http")
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
from http import HTTPStatus
|
|
||||||
|
|
||||||
from aurweb.templates import make_context, render_template
|
|
||||||
|
|
||||||
|
|
||||||
async def not_found(request, exc):
|
|
||||||
context = make_context(request, "Page Not Found")
|
|
||||||
return render_template(request, "errors/404.html", context,
|
|
||||||
HTTPStatus.NOT_FOUND)
|
|
||||||
|
|
||||||
|
|
||||||
async def service_unavailable(request, exc):
|
|
||||||
context = make_context(request, "Service Unavailable")
|
|
||||||
return render_template(request, "errors/503.html", context,
|
|
||||||
HTTPStatus.SERVICE_UNAVAILABLE)
|
|
||||||
|
|
||||||
# Maps HTTP errors to functions
|
|
||||||
exceptions = {
|
|
||||||
404: not_found,
|
|
||||||
503: service_unavailable
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
{% extends 'partials/layout.html' %}
|
|
||||||
|
|
||||||
{% block pageContent %}
|
|
||||||
<div id="error-page" class="box 404">
|
|
||||||
<h2>404 - {% trans %}Page Not Found{% endtrans %}</h2>
|
|
||||||
<p>{% trans %}Sorry, the page you've requested does not exist.{% endtrans %}</p>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
|
@ -1,8 +0,0 @@
|
||||||
{% extends 'partials/layout.html' %}
|
|
||||||
|
|
||||||
{% block pageContent %}
|
|
||||||
<div id="error-page" class="box 503">
|
|
||||||
<h2>503 - {% trans %}Service Unavailable{% endtrans %}</h2>
|
|
||||||
<p>{% trans %}Don't panic! This site is down due to maintenance. We will be back soon.{% endtrans %}</p>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
8
templates/errors/detail.html
Normal file
8
templates/errors/detail.html
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{% extends 'partials/layout.html' %}
|
||||||
|
|
||||||
|
{% block pageContent %}
|
||||||
|
<div id="error-page" class="box">
|
||||||
|
<h2>{{ "%d" | format(exc.status_code) }} - {{ phrase }}</h2>
|
||||||
|
<p>{{ exc.detail }}</p>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
|
@ -11,6 +11,8 @@ import aurweb.asgi
|
||||||
import aurweb.config
|
import aurweb.config
|
||||||
import aurweb.redis
|
import aurweb.redis
|
||||||
|
|
||||||
|
from aurweb.testing.requests import Request
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_asgi_startup_session_secret_exception(monkeypatch):
|
async def test_asgi_startup_session_secret_exception(monkeypatch):
|
||||||
|
@ -42,9 +44,11 @@ async def test_asgi_startup_exception(monkeypatch):
|
||||||
async def test_asgi_http_exception_handler():
|
async def test_asgi_http_exception_handler():
|
||||||
exc = HTTPException(status_code=422, detail="EXCEPTION!")
|
exc = HTTPException(status_code=422, detail="EXCEPTION!")
|
||||||
phrase = http.HTTPStatus(exc.status_code).phrase
|
phrase = http.HTTPStatus(exc.status_code).phrase
|
||||||
response = await aurweb.asgi.http_exception_handler(None, exc)
|
response = await aurweb.asgi.http_exception_handler(Request(), exc)
|
||||||
assert response.body.decode() == \
|
assert response.status_code == 422
|
||||||
f"<h1>{exc.status_code} {phrase}</h1><p>{exc.detail}</p>"
|
content = response.body.decode()
|
||||||
|
assert f"{exc.status_code} - {phrase}" in content
|
||||||
|
assert "EXCEPTION!" in content
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
|
|
Loading…
Add table
Reference in a new issue