feat: modernize error page (#2949)
* can't figure this out! * raise here so it gets picked up by exceptions * add few more info for error rendering * add a few more checks for browser not fail safe just one more layer * cleaner error display ... hopefully * add go to extension * keep buttons add go to extension * feat: identify extensions that are not installed * fix: status code * fix: full path * add account/logout button if 401 prevent getting stuck * fix: ext access * fix user button * fix: 404 page * fix: json 404 response * fix: dumb rendering * fix: `/api` request always json * fix: extension api path * test: check regtest * test: investgate * something made ws slower? * fix: change error code --------- Co-authored-by: Vlad Stan <stan.v.vlad@gmail.com> Co-authored-by: dni ⚡ <office@dnilabs.com> Co-authored-by: Arc <33088785+arcbtc@users.noreply.github.com>
This commit is contained in:
co-authored by
Vlad Stan
dni ⚡
Arc
parent
eeca7de10d
commit
4511891297
+54
-3
@@ -8,7 +8,9 @@ from fastapi.exceptions import RequestValidationError
|
||||
from fastapi.responses import JSONResponse, RedirectResponse, Response
|
||||
from loguru import logger
|
||||
|
||||
from .helpers import template_renderer
|
||||
from lnbits.settings import settings
|
||||
|
||||
from .helpers import path_segments, template_renderer
|
||||
|
||||
|
||||
class PaymentError(Exception):
|
||||
@@ -26,9 +28,11 @@ class InvoiceError(Exception):
|
||||
def render_html_error(request: Request, exc: Exception) -> Optional[Response]:
|
||||
# Only the browser sends "text/html" request
|
||||
# not fail proof, but everything else get's a JSON response
|
||||
|
||||
if not request.headers:
|
||||
return None
|
||||
if "text/html" not in request.headers.get("accept", ""):
|
||||
|
||||
if not _is_browser_request(request):
|
||||
return None
|
||||
|
||||
if (
|
||||
@@ -49,7 +53,14 @@ def render_html_error(request: Request, exc: Exception) -> Optional[Response]:
|
||||
)
|
||||
|
||||
return template_renderer().TemplateResponse(
|
||||
request, "error.html", {"err": f"Error: {exc!s}"}, status_code
|
||||
request,
|
||||
"error.html",
|
||||
{
|
||||
"err": f"Error: {exc!s}",
|
||||
"status_code": int(status_code),
|
||||
"message": str(exc).split(":")[-1].strip(),
|
||||
},
|
||||
status_code,
|
||||
)
|
||||
|
||||
|
||||
@@ -119,3 +130,43 @@ def register_exception_handlers(app: FastAPI):
|
||||
status_code=520,
|
||||
content={"detail": exc.message, "status": exc.status},
|
||||
)
|
||||
|
||||
@app.exception_handler(404)
|
||||
async def error_handler_404(request: Request, exc: HTTPException):
|
||||
logger.error(f"404: {request.url.path} {exc.status_code}: {exc.detail}")
|
||||
|
||||
if not _is_browser_request(request):
|
||||
return JSONResponse(
|
||||
status_code=exc.status_code,
|
||||
content={"detail": exc.detail},
|
||||
)
|
||||
|
||||
path = path_segments(request.url.path)[0]
|
||||
status_code = HTTPStatus.NOT_FOUND
|
||||
message: str = "Page not found."
|
||||
|
||||
if path in settings.lnbits_all_extensions_ids:
|
||||
status_code = HTTPStatus.FORBIDDEN
|
||||
message = f"Extension '{path}' not installed. Ask the admin to install it."
|
||||
|
||||
return template_renderer().TemplateResponse(
|
||||
request,
|
||||
"error.html",
|
||||
{"status_code": int(status_code), "message": message},
|
||||
int(status_code),
|
||||
)
|
||||
|
||||
|
||||
def _is_browser_request(request: Request) -> bool:
|
||||
# Check a few common browser agents, also not fail proof
|
||||
if "api/v1" in request.url.path:
|
||||
return False
|
||||
|
||||
browser_agents = ["Mozilla", "Chrome", "Safari"]
|
||||
if any(agent in request.headers.get("user-agent", "") for agent in browser_agents):
|
||||
return True
|
||||
|
||||
if "text/html" in request.headers.get("accept", ""):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user