diff --git a/examples/exc.py b/examples/exc.py index c02ee0b..c6994aa 100644 --- a/examples/exc.py +++ b/examples/exc.py @@ -1,4 +1,12 @@ +from httpout import run + + print('Hi') -raise ValueError + +async def main(): + raise ValueError + + +run(main()) diff --git a/httpout/httpout.py b/httpout/httpout.py index 42b24e9..4f78d8b 100644 --- a/httpout/httpout.py +++ b/httpout/httpout.py @@ -5,7 +5,6 @@ import os import sys -from traceback import TracebackException from types import ModuleType from awaiter import MultiThreadExecutor @@ -277,32 +276,7 @@ async def _on_request(self, **server): ctx.module_path = module_path except BaseException as exc: await server['response'].join() - - if not response.headers_sent(): - response.set_status(500, b'Internal Server Error') - response.set_content_type(b'text/html; charset=utf-8') - request.http_keepalive = False - - if isinstance(exc, Exception): - if request.protocol.options['debug']: - te = TracebackException.from_exception(exc) - await response.write( - b'\n' % b'
  • '.join( - html_escape(line) - .encode() for line in te.format() - ) - ) - else: - await response.write( - f'\n' - .encode() - ) - elif isinstance(exc, SystemExit): - if exc.code: - await response.write(str(exc.code).encode()) - else: - request.protocol.print_exception(exc) + await server['response'].handle_exception(exc) finally: await g.executor.submit( cleanup_modules, server['modules'], excludes diff --git a/httpout/lib/http_response.py b/httpout/lib/http_response.py index 7efe514..b6b29df 100644 --- a/httpout/lib/http_response.py +++ b/httpout/lib/http_response.py @@ -3,6 +3,9 @@ import asyncio import concurrent.futures +from traceback import TracebackException +from tremolo.utils import html_escape + class HTTPResponse: def __init__(self, response): @@ -24,6 +27,33 @@ async def join(self): while self.tasks: await self.tasks.pop() + async def handle_exception(self, exc): + if not self.response.headers_sent(): + self.response.set_status(500, b'Internal Server Error') + self.response.set_content_type(b'text/html; charset=utf-8') + self.response.request.http_keepalive = False + + if isinstance(exc, Exception): + if self.response.request.protocol.options['debug']: + te = TracebackException.from_exception(exc) + await self.response.write( + b'\n' % b'
  • '.join( + html_escape(line) + .encode() for line in te.format() + ) + ) + else: + await self.response.write( + f'\n' + .encode() + ) + elif isinstance(exc, SystemExit): + if exc.code: + await self.response.write(str(exc.code).encode()) + else: + self.response.request.protocol.print_exception(exc) + def run_coroutine(self, coro): fut = concurrent.futures.Future() @@ -35,7 +65,9 @@ async def callback(): fut.set_result(result) except BaseException as exc: if not fut.done(): - fut.set_exception(exc) + fut.set_result(None) + + await self.handle_exception(exc) self.loop.call_soon_threadsafe(self.create_task, callback()) return fut