From 6e1a3517764e93f719195f7f6b071c82f238a224 Mon Sep 17 00:00:00 2001 From: "alex.oleshkevich" Date: Wed, 21 Jun 2023 19:50:13 +0200 Subject: [PATCH] Remove middleware --- README.md | 59 +----------------- examples/fastapi.py | 14 ----- starception/__init__.py | 2 - starception/middleware.py | 60 ------------------- ...test_middleware.py => test_starception.py} | 24 -------- 5 files changed, 2 insertions(+), 157 deletions(-) delete mode 100644 examples/fastapi.py delete mode 100644 starception/middleware.py rename tests/{test_middleware.py => test_starception.py} (50%) diff --git a/README.md b/README.md index dedabc4..f5da0c3 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ poetry add starception -E pygments * exception chains * dark theme -The middleware will automatically mask any value which key contains `key`, `secret`, `token`, `password`. +Starception automatically masks any value which key contains `key`, `secret`, `token`, `password`. ## Quick start @@ -63,12 +63,9 @@ See example application in [examples/](examples/) directory of this repository. ## Usage -Starception will work only in debug mode so don't forget to set `debug=True` for local development. - -### Monkey patching Starlette +Starception will work only in debug mode so don't forget to set `Starlette.debug=True`. To replace built-in debug exception handler call `install_error_handler` before you create Starlette instance. -> Currently, this is a recommended approach. ```python from starception import install_error_handler @@ -78,58 +75,6 @@ install_error_handler() app = Starlette() ``` -### Using middleware - -To render a beautiful exception page you need to install a `StarceptionMiddleware` middleware to your application. - - -> Note, to catch as many exceptions as possible the middleware has to be the first one in the stack. - -```python -import typing - -from starlette.applications import Starlette -from starlette.middleware import Middleware -from starlette.requests import Request -from starlette.routing import Route - -from starception import StarceptionMiddleware - - -async def index_view(request: Request) -> typing.NoReturn: - raise TypeError('Oops, something really went wrong...') - - -app = Starlette( - debug=True, - routes=[Route('/', index_view)], - middleware=[ - Middleware(StarceptionMiddleware), - # other middleware go here - ], -) -``` - -### Integration with FastAPI - -Attach `StarceptionMiddleware` middleware to your FastAPI application: - -```python -import typing - -from fastapi import FastAPI, Request - -from starception import StarceptionMiddleware - -app = FastAPI(debug=True) -app.add_middleware(StarceptionMiddleware) # must be the first one! - - -@app.route('/') -async def index_view(request: Request) -> typing.NoReturn: - raise TypeError('Oops, something really went wrong...') -``` - ### Integration with other frameworks `starception` exports `starception.exception_handler(request, exc)` function, which you can use in your diff --git a/examples/fastapi.py b/examples/fastapi.py deleted file mode 100644 index 66a14d7..0000000 --- a/examples/fastapi.py +++ /dev/null @@ -1,14 +0,0 @@ -import typing -from fastapi import FastAPI, Request - -from starception import StarceptionMiddleware - -app = FastAPI(debug=True) -app.add_middleware(StarceptionMiddleware) - - -@app.route('/') -def index_view(request: Request) -> typing.NoReturn: - request.state.token = 'mytoken' - request.app.state.app_token = 'app mytoken' - raise TypeError('Oops, something really went wrong...') diff --git a/starception/__init__.py b/starception/__init__.py index 170f259..d56325a 100644 --- a/starception/__init__.py +++ b/starception/__init__.py @@ -1,8 +1,6 @@ from starception.exception_handler import add_link_template, exception_handler, install_error_handler, set_editor -from starception.middleware import StarceptionMiddleware __all__ = [ - 'StarceptionMiddleware', 'exception_handler', 'set_editor', 'add_link_template', diff --git a/starception/middleware.py b/starception/middleware.py deleted file mode 100644 index ea801c7..0000000 --- a/starception/middleware.py +++ /dev/null @@ -1,60 +0,0 @@ -from starlette.requests import Request -from starlette.responses import PlainTextResponse, Response -from starlette.types import ASGIApp, Message, Receive, Scope, Send - -from starception.exception_handler import exception_handler - - -class StarceptionMiddleware: - """ - Handles returning 500 responses when a server error occurs. - - If 'debug' is set, then traceback responses will be returned, otherwise the - designated 'handler' will be called. - - This middleware class should generally be used to wrap *everything* else up, - so that unhandled exceptions anywhere in the stack always result in an - appropriate 500 response. - """ - - def __init__(self, app: ASGIApp) -> None: - self.app = app - - async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: - if scope["type"] != "http": # pragma: nocover - await self.app(scope, receive, send) - return - - response_started = False - - async def _send(message: Message) -> None: - nonlocal response_started, send - - if message["type"] == "http.response.start": # pragma: nocover - response_started = True - await send(message) - - try: - await self.app(scope, receive, _send) - except Exception as exc: - if not response_started: - request = Request(scope) - if request.app.debug: - # In debug mode, return traceback responses. - response = self.debug_response(request, exc) - else: - # Use our default 500 error handler. - response = self.error_response(request, exc) - - await response(scope, receive, send) - - # We always continue to raise the exception. - # This allows servers to log the error, or allows test clients - # to optionally raise the error within the test case. - raise exc - - def debug_response(self, request: Request, exc: Exception) -> Response: - return exception_handler(request, exc) - - def error_response(self, request: Request, exc: Exception) -> Response: - return PlainTextResponse("Internal Server Error", status_code=500) diff --git a/tests/test_middleware.py b/tests/test_starception.py similarity index 50% rename from tests/test_middleware.py rename to tests/test_starception.py index 6a9e29d..78b3220 100644 --- a/tests/test_middleware.py +++ b/tests/test_starception.py @@ -1,11 +1,9 @@ import typing from starlette.applications import Starlette -from starlette.middleware import Middleware from starlette.requests import Request from starlette.routing import Route from starlette.testclient import TestClient -from starception import StarceptionMiddleware from starception.exception_handler import install_error_handler @@ -13,19 +11,10 @@ def view(request: Request) -> typing.NoReturn: raise TypeError('Oops') -debug_app = Starlette(debug=True, routes=[Route('/', view)], middleware=[Middleware(StarceptionMiddleware)]) -release_app = Starlette(debug=False, routes=[Route('/', view)], middleware=[Middleware(StarceptionMiddleware)]) no_middleware_debug_app = Starlette(debug=True, routes=[Route('/', view)]) no_middleware_release_app = Starlette(debug=False, routes=[Route('/', view)]) -def test_middleware_renders_html_page_in_debug_mode() -> None: - client = TestClient(debug_app, raise_server_exceptions=False) - response = client.get('/', headers={'accept': 'text/html'}) - assert '' in response.text - assert 'Oops' in response.text - - def test_middleware_renders_html_page_with_handler_installed_in_debug_mode() -> None: install_error_handler() client = TestClient(no_middleware_debug_app, raise_server_exceptions=False) @@ -39,16 +28,3 @@ def test_middleware_renders_plain_text_page_with_handler_installed_in_release_mo client = TestClient(no_middleware_release_app, raise_server_exceptions=False) response = client.get('/', headers={'accept': 'text/html'}) assert 'Internal Server Error' in response.text - - -def test_middleware_renders_plain_text_page_in_debug_mode_for_non_html() -> None: - client = TestClient(debug_app, raise_server_exceptions=False) - response = client.get('/', headers={'accept': 'text/plain'}) - assert '' not in response.text - assert 'Oops' in response.text - - -def test_middleware_renders_plain_text_in_release_mode() -> None: - client = TestClient(release_app, raise_server_exceptions=False) - response = client.get('/', headers={'accept': 'text/html'}) - assert 'Internal Server Error' in response.text