mirror of
https://gitlab.archlinux.org/archlinux/aurweb.git
synced 2025-02-03 10:43:03 +01:00
fix(FastAPI): add custom error templates for certain exceptions
Signed-off-by: Steven Guikal <void@fluix.one>
This commit is contained in:
parent
51b60f4210
commit
e126d431d7
4 changed files with 70 additions and 4 deletions
|
@ -1,6 +1,7 @@
|
|||
import asyncio
|
||||
import http
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import typing
|
||||
|
||||
|
@ -9,18 +10,22 @@ from urllib.parse import quote_plus
|
|||
from fastapi import FastAPI, HTTPException, Request, Response
|
||||
from fastapi.responses import RedirectResponse
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from jinja2 import TemplateNotFound
|
||||
from prometheus_client import multiprocess
|
||||
from sqlalchemy import and_, or_
|
||||
from starlette.exceptions import HTTPException as StarletteHTTPException
|
||||
from starlette.middleware.authentication import AuthenticationMiddleware
|
||||
from starlette.middleware.sessions import SessionMiddleware
|
||||
|
||||
import aurweb.config
|
||||
import aurweb.logging
|
||||
import aurweb.pkgbase.util as pkgbaseutil
|
||||
|
||||
from aurweb import prometheus, util
|
||||
from aurweb.auth import BasicAuthBackend
|
||||
from aurweb.db import get_engine, query
|
||||
from aurweb.models import AcceptedTerm, Term
|
||||
from aurweb.packages.util import get_pkg_or_base
|
||||
from aurweb.prometheus import instrumentator
|
||||
from aurweb.routers import APP_ROUTES
|
||||
from aurweb.templates import make_context, render_template
|
||||
|
@ -89,7 +94,7 @@ def child_exit(server, worker): # pragma: no cover
|
|||
multiprocess.mark_process_dead(worker.pid)
|
||||
|
||||
|
||||
@app.exception_handler(HTTPException)
|
||||
@app.exception_handler(StarletteHTTPException)
|
||||
async def http_exception_handler(request: Request, exc: HTTPException) \
|
||||
-> Response:
|
||||
""" Handle an HTTPException thrown in a route. """
|
||||
|
@ -97,8 +102,24 @@ async def http_exception_handler(request: Request, exc: HTTPException) \
|
|||
context = make_context(request, phrase)
|
||||
context["exc"] = exc
|
||||
context["phrase"] = phrase
|
||||
return render_template(request, "errors/detail.html", context,
|
||||
exc.status_code)
|
||||
|
||||
# Additional context for some exceptions.
|
||||
if exc.status_code == http.HTTPStatus.NOT_FOUND:
|
||||
tokens = request.url.path.split("/")
|
||||
matches = re.match("^([a-z0-9][a-z0-9.+_-]*?)(\\.git)?$", tokens[1])
|
||||
if matches:
|
||||
try:
|
||||
pkgbase = get_pkg_or_base(matches.group(1))
|
||||
context = pkgbaseutil.make_context(request, pkgbase)
|
||||
except HTTPException:
|
||||
pass
|
||||
|
||||
try:
|
||||
return render_template(request, f"errors/{exc.status_code}.html",
|
||||
context, exc.status_code)
|
||||
except TemplateNotFound:
|
||||
return render_template(request, "errors/detail.html",
|
||||
context, exc.status_code)
|
||||
|
||||
|
||||
@app.middleware("http")
|
||||
|
|
|
@ -87,11 +87,14 @@ def provides_markup(provides: Providers) -> str:
|
|||
|
||||
def get_pkg_or_base(
|
||||
name: str,
|
||||
cls: Union[models.Package, models.PackageBase] = models.PackageBase):
|
||||
cls: Union[models.Package, models.PackageBase] = models.PackageBase) \
|
||||
-> Union[models.Package, models.PackageBase]:
|
||||
""" Get a PackageBase instance by its name or raise a 404 if
|
||||
it can't be found in the database.
|
||||
|
||||
:param name: {Package,PackageBase}.Name
|
||||
:param exception: Whether to raise an HTTPException or simply return None if
|
||||
the package can't be found.
|
||||
:raises HTTPException: With status code 404 if record doesn't exist
|
||||
:return: {Package,PackageBase} instance
|
||||
"""
|
||||
|
|
34
templates/errors/404.html
Normal file
34
templates/errors/404.html
Normal file
|
@ -0,0 +1,34 @@
|
|||
{% extends 'partials/layout.html' %}
|
||||
|
||||
{% block pageContent %}
|
||||
<div id="error-page" class="box">
|
||||
<h2>404 - {% trans %}Page Not Found{% endtrans %}</h2>
|
||||
<p>{% trans %}Sorry, the page you've requested does not exist.{% endtrans %}</p>
|
||||
{% if pkgbase %}
|
||||
<ul>
|
||||
{% set pkgname_strong="<strong>%s</strong>" | format(pkgbase.Name) %}
|
||||
<li>
|
||||
<strong>{% trans %}Note{% endtrans %}:</strong>
|
||||
{% trans %}Git clone URLs are not meant to be opened in a browser.{% endtrans %}
|
||||
</li>
|
||||
<li>
|
||||
{% set gitcmd="<code>git clone %s</code>" | format(git_clone_uri_anon | format(pkgbase.Name)) %}
|
||||
{% if is_maintainer %}
|
||||
{% set gitcmd="<code>git clone %s</code>" | format(git_clone_uri_priv | format(pkgbase.Name)) %}
|
||||
{% endif %}
|
||||
{{
|
||||
"To clone the Git repository of %s, run %s."
|
||||
| tr | format(pkgname_strong, gitcmd) | safe
|
||||
}}
|
||||
</li>
|
||||
<li>
|
||||
{% set pkglink='<a href="/pkgbase/%s">' | format(pkgbase.Name) %}
|
||||
{{
|
||||
"Click %shere%s to return to the %s details page."
|
||||
| tr | format(pkglink, "</a>", pkgname_strong) | safe
|
||||
}}
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
8
templates/errors/503.html
Normal file
8
templates/errors/503.html
Normal file
|
@ -0,0 +1,8 @@
|
|||
{% extends 'partials/layout.html' %}
|
||||
|
||||
{% block pageContent %}
|
||||
<div id="error-page" class="box">
|
||||
<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 %}
|
Loading…
Add table
Reference in a new issue