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.exceptions import BadRequest, SanicException
|
||||||
from sanic.helpers import STATUS_CODES
|
from sanic.helpers import STATUS_CODES
|
||||||
from sanic.response import html, json, text
|
from sanic.response import html, json, text
|
||||||
from sanic.pages.base import ErrorPage
|
from sanic.pages.error import ErrorPage
|
||||||
|
|
||||||
dumps: t.Callable[..., str]
|
dumps: t.Callable[..., str]
|
||||||
try:
|
try:
|
||||||
@ -160,7 +160,13 @@ class HTMLRenderer(BaseRenderer):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def _page(self, full: bool) -> HTTPResponse:
|
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)
|
return html(page.render(), status=self.status, headers=self.headers)
|
||||||
|
|
||||||
def full(self) -> HTTPResponse:
|
def full(self) -> HTTPResponse:
|
||||||
|
@ -24,6 +24,7 @@ class AutoIndex(BasePage):
|
|||||||
table.autoindex td:first-child { flex: 1; }
|
table.autoindex td:first-child { flex: 1; }
|
||||||
table.autoindex td:nth-child(2) { text-align: right; }
|
table.autoindex td:nth-child(2) { text-align: right; }
|
||||||
table.autoindex td:last-child { text-align: right; }
|
table.autoindex td:last-child { text-align: right; }
|
||||||
|
span.icon { margin-right: 1rem; }
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
TITLE = "File browser"
|
TITLE = "File browser"
|
||||||
|
@ -16,12 +16,15 @@ class BasePage(ABC):
|
|||||||
display: flex; align-items: center; justify-content: space-between;
|
display: flex; align-items: center; justify-content: space-between;
|
||||||
background: #555; color: #e1e1e1;
|
background: #555; color: #e1e1e1;
|
||||||
}
|
}
|
||||||
|
main { padding-bottom: 3rem; }
|
||||||
|
h2 { margin: 2rem 0 1rem 0; }
|
||||||
a:visited { color: inherit; }
|
a:visited { color: inherit; }
|
||||||
a { text-decoration: none; color: #88f; }
|
a { text-decoration: none; color: #88f; }
|
||||||
a:hover, a:focus { text-decoration: underline; outline: none; }
|
a:hover, a:focus { text-decoration: underline; outline: none; }
|
||||||
#logo { height: 2.5rem; }
|
#logo { height: 2.5rem; }
|
||||||
table { width: 100%; max-width: 1200px; }
|
.smalltext { font-size: 1rem; }
|
||||||
span.icon { margin-right: 1rem; }
|
.nobr { white-space: nowrap; }
|
||||||
|
table { width: 100%; max-width: 1200px; word-break: break-all; }
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
html { background: #111; color: #ccc; }
|
html { background: #111; color: #ccc; }
|
||||||
}
|
}
|
||||||
@ -50,24 +53,3 @@ class BasePage(ABC):
|
|||||||
@abstractmethod
|
@abstractmethod
|
||||||
def _body(self) -> None:
|
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