Refactored to sanic.pages.error module. Traceback and style tuning. Print also headers, and for other than 500 errors as well. 500 error message text UX workaround.
This commit is contained in:
parent
77bdfa14ed
commit
ea09906e0a
@ -23,7 +23,7 @@ from traceback import extract_tb
|
||||
from sanic.exceptions import BadRequest, SanicException
|
||||
from sanic.helpers import STATUS_CODES
|
||||
from sanic.response import html, json, text
|
||||
from sanic.pages.base import ErrorPage
|
||||
from sanic.pages.error import ErrorPage
|
||||
|
||||
dumps: t.Callable[..., str]
|
||||
try:
|
||||
@ -160,7 +160,13 @@ class HTMLRenderer(BaseRenderer):
|
||||
)
|
||||
|
||||
def _page(self, full: bool) -> HTTPResponse:
|
||||
page = ErrorPage(super().title, super().text, sys.exc_info()[1], full=full)
|
||||
page = ErrorPage(
|
||||
title=super().title,
|
||||
text=super().text,
|
||||
request=self.request,
|
||||
exc=self.exception,
|
||||
full=full,
|
||||
)
|
||||
return html(page.render(), status=self.status, headers=self.headers)
|
||||
|
||||
def full(self) -> HTTPResponse:
|
||||
|
@ -24,6 +24,7 @@ class AutoIndex(BasePage):
|
||||
table.autoindex td:first-child { flex: 1; }
|
||||
table.autoindex td:nth-child(2) { text-align: right; }
|
||||
table.autoindex td:last-child { text-align: right; }
|
||||
span.icon { margin-right: 1rem; }
|
||||
"""
|
||||
)
|
||||
TITLE = "File browser"
|
||||
|
@ -16,12 +16,15 @@ class BasePage(ABC):
|
||||
display: flex; align-items: center; justify-content: space-between;
|
||||
background: #555; color: #e1e1e1;
|
||||
}
|
||||
main { padding-bottom: 3rem; }
|
||||
h2 { margin: 2rem 0 1rem 0; }
|
||||
a:visited { color: inherit; }
|
||||
a { text-decoration: none; color: #88f; }
|
||||
a:hover, a:focus { text-decoration: underline; outline: none; }
|
||||
#logo { height: 2.5rem; }
|
||||
table { width: 100%; max-width: 1200px; }
|
||||
span.icon { margin-right: 1rem; }
|
||||
.smalltext { font-size: 1rem; }
|
||||
.nobr { white-space: nowrap; }
|
||||
table { width: 100%; max-width: 1200px; word-break: break-all; }
|
||||
@media (prefers-color-scheme: dark) {
|
||||
html { background: #111; color: #ccc; }
|
||||
}
|
||||
@ -50,24 +53,3 @@ class BasePage(ABC):
|
||||
@abstractmethod
|
||||
def _body(self) -> None:
|
||||
...
|
||||
|
||||
|
||||
class ErrorPage(BasePage):
|
||||
TITLE = "Error while handling your request"
|
||||
|
||||
def __init__(self, title: str, text: str, exc: Exception, full: bool) -> None:
|
||||
super().__init__()
|
||||
self.title = title
|
||||
self.text = text
|
||||
self.exc = exc
|
||||
self.full = full
|
||||
|
||||
def _body(self) -> None:
|
||||
with self.doc.main:
|
||||
self.doc.h1(f"⚠️ {self.title}")
|
||||
if self.full and self.exc:
|
||||
from niceback import html_traceback
|
||||
self.doc(html_traceback(self.exc))
|
||||
else:
|
||||
self.doc.p(self.text)
|
||||
|
||||
|
40
sanic/pages/error.py
Normal file
40
sanic/pages/error.py
Normal file
@ -0,0 +1,40 @@
|
||||
from .base import BasePage
|
||||
from sanic.request import Request
|
||||
|
||||
from html5tagger import E
|
||||
from niceback import html_traceback, inspector
|
||||
|
||||
# Avoid showing the request in the traceback variable inspectors
|
||||
inspector.blacklist_types += Request,
|
||||
|
||||
class ErrorPage(BasePage):
|
||||
def __init__(self, title: str, text: str, request: Request, exc: Exception, full: bool) -> None:
|
||||
super().__init__()
|
||||
# Internal server errors come with the text of the exception, which we don't want to show to the user.
|
||||
# FIXME: This needs to be done some place else but I am not digging into that now.
|
||||
if "Internal Server Error" in title:
|
||||
text = "The application encountered an unexpected error and could not continue."
|
||||
self.TITLE = E(f"App {request.app.name} cannot handle your request")
|
||||
self.title = title
|
||||
self.text = text
|
||||
self.request = request
|
||||
self.exc = exc
|
||||
self.full = full
|
||||
|
||||
def _body(self) -> None:
|
||||
with self.doc.main:
|
||||
self.doc.h1(f"⚠️ {self.title}").p(self.text)
|
||||
if not self.request.app.debug:
|
||||
return
|
||||
# Show additional details in debug mode, open by default for 500 errors
|
||||
with self.doc.details(open=self.full, class_="smalltext"):
|
||||
self.doc.summary("Details for developers (Sanic debug mode only)")
|
||||
if self.exc:
|
||||
self.doc.h2(f"Exception in {self.request.route.name}:")
|
||||
# skip_outmost=1 to hide Sanic.handle_request
|
||||
self.doc(html_traceback(self.exc, skip_outmost=1))
|
||||
|
||||
self.doc.h2(f"{self.request.method} {self.request.path}")
|
||||
with self.doc.table(id="request-headers"):
|
||||
for k, v in self.request.headers.items():
|
||||
self.doc.tr.td(f"{k}:", class_="nobr").td(v)
|
Loading…
x
Reference in New Issue
Block a user