107 lines
2.8 KiB
Python
107 lines
2.8 KiB
Python
import logging
|
|
import asyncio
|
|
|
|
from aiohttp import web
|
|
from aiohttp.web import Response
|
|
from aiohttp.web_exceptions import HTTPNotFound
|
|
|
|
from ..util import stringify, format_tb, Addr
|
|
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
@web.middleware
|
|
async def errors_handler_middleware(request, handler):
|
|
try:
|
|
response = await handler(request)
|
|
return response
|
|
|
|
except HTTPNotFound:
|
|
return web.json_response({'error': 'not found'}, status=404)
|
|
|
|
except Exception as exc:
|
|
_logger.exception(exc)
|
|
data = {
|
|
'error': exc.__class__.__name__,
|
|
'message': exc.message if hasattr(exc, 'message') else str(exc)
|
|
}
|
|
tb = format_tb(exc)
|
|
if tb:
|
|
data['stacktrace'] = tb
|
|
|
|
return web.json_response(data, status=500)
|
|
|
|
|
|
def serve(addr: Addr, route_table: web.RouteTableDef, handle_signals: bool = True):
|
|
app = web.Application()
|
|
app.add_routes(route_table)
|
|
app.middlewares.append(errors_handler_middleware)
|
|
|
|
host, port = addr
|
|
|
|
web.run_app(app,
|
|
host=host,
|
|
port=port,
|
|
handle_signals=handle_signals)
|
|
|
|
|
|
def routes() -> web.RouteTableDef:
|
|
return web.RouteTableDef()
|
|
|
|
|
|
def ok(data=None):
|
|
if data is None:
|
|
data = 1
|
|
response = {'response': data}
|
|
return web.json_response(response, dumps=stringify)
|
|
|
|
|
|
class HTTPServer:
|
|
def __init__(self, addr: Addr, handle_errors=True):
|
|
self.addr = addr
|
|
self.app = web.Application()
|
|
self.logger = logging.getLogger(self.__class__.__name__)
|
|
|
|
if handle_errors:
|
|
self.app.middlewares.append(errors_handler_middleware)
|
|
|
|
def _add_route(self,
|
|
method: str,
|
|
path: str,
|
|
handler: callable):
|
|
self.app.router.add_routes([getattr(web, method)(path, handler)])
|
|
|
|
def get(self, path, handler):
|
|
self._add_route('get', path, handler)
|
|
|
|
def post(self, path, handler):
|
|
self._add_route('post', path, handler)
|
|
|
|
def put(self, path, handler):
|
|
self._add_route('put', path, handler)
|
|
|
|
def delete(self, path, handler):
|
|
self._add_route('delete', path, handler)
|
|
|
|
def run(self, event_loop=None, handle_signals=True):
|
|
if not event_loop:
|
|
event_loop = asyncio.get_event_loop()
|
|
|
|
runner = web.AppRunner(self.app, handle_signals=handle_signals)
|
|
event_loop.run_until_complete(runner.setup())
|
|
|
|
host, port = self.addr
|
|
site = web.TCPSite(runner, host=host, port=port)
|
|
event_loop.run_until_complete(site.start())
|
|
|
|
self.logger.info(f'Server started at http://{host}:{port}')
|
|
|
|
event_loop.run_forever()
|
|
|
|
def ok(self, data=None):
|
|
return ok(data)
|
|
|
|
def plain(self, text: str):
|
|
return Response(text=text, content_type='text/plain')
|