http_server_async: reuse response

This commit is contained in:
Izalia Mae 2021-10-24 13:22:41 -04:00
parent 5f79d2796f
commit dd2f3df431
3 changed files with 53 additions and 34 deletions

View file

@ -166,6 +166,7 @@ class Application:
try:
request = self.cfg.request_class(self, reader, writer.get_extra_info('peername')[0])
response = self.cfg.response_class()
await request.parse_headers()
handler = self.get_route(request.path, request.method)
@ -173,10 +174,10 @@ class Application:
await self.handle_middleware(request)
if handler.params:
handler_response = await handler.target(request, **handler.params)
handler_response = await handler.target(request, response, **handler.params)
else:
handler_response = await handler.target(request)
handler_response = await handler.target(request, response)
if isinstance(handler_response, dict):
response = self.cfg.response_class(**handler_response)
@ -184,41 +185,31 @@ class Application:
elif isinstance(handler_response, Response):
response = handler_response
elif not handler_response:
pass
else:
raise error.ServerError()
except NotFound:
response = self.cfg.response_class()
response.error('Not Found', 404)
except MethodNotAllowed:
response = self.cfg.response_class()
response.error('Method Not Allowed', 405)
except error.HttpError as e:
response = self.cfg.response_class()
response.error(e.message, e.status)
except:
traceback.print_exc()
response = self.cfg.response_class()
response.error('Server Error', 500)
try:
await self.handle_middleware(request, response)
except NotFound:
response = self.cfg.response_class.new_error('Not Found', 404)
except MethodNotAllowed:
response = self.cfg.response_class.new_error('Method Not Allowed', 405)
except error.HttpError as e:
response = self.cfg.response_class.new_error(e.message, e.status)
except:
traceback.print_exc()
response = Response()
response.error('Server Error', 500)
response = self.cfg.response_class.new_error('Server Error', 500)
try:
response.headers.update(self.cfg.default_headers)
writer.write(response.compile())
await writer.drain()
writer.close()
await writer.wait_closed()
if request:
logging.info(f'{request.remote} {request.method} {request.path} {response.status} {len(response.body)} {request.agent}')
@ -226,6 +217,9 @@ class Application:
except:
traceback.print_exc()
writer.close()
await writer.wait_closed()
async def handle_middleware(self, request, response=None):
for middleware in self.middleware['response' if response else 'request']:

View file

@ -49,26 +49,50 @@ class Response:
self._body += self._parse_body_data(data)
def delete_cookie(self, cookie):
cookie.set_delete()
self.cookies[cookie.key] = cookie
@classmethod
def new_html(cls, body, **kwargs):
response = cls(**kwargs)
response.set_html(body)
return response
@classmethod
def new_json(cls, body, activity=False, **kwargs):
response = cls(**kwargs)
response.set_json(body, activity)
return response
@classmethod
def new_error(cls, message, status=500, **kwargs):
response = cls(**kwargs)
response.set_error(message, status)
return response
def set_html(self, body=b''):
self.content_type = 'text/html'
self.body = body
def json(self, body={}, activity=False):
def set_json(self, body={}, activity=False):
self.content_type = 'application/activity+json' if activity else 'application/json'
self.body = body
def error(self, message, status=500):
def set_error(self, message, status=500):
self.body = f'HTTP Error {status}: {message}'
self.status = status
def delete_cookie(self, cookie):
cookie.set_delete()
self.cookies[cookie.key] = cookie
def compile(self):
data = bytes(f'HTTP/1.1 {self.status}', 'utf-8')

View file

@ -33,7 +33,7 @@ class View:
def Static(src):
src = Path(src)
async def StaticHandler(request, path=None):
async def StaticHandler(request, response, path=None):
try:
if not path:
src_path = src
@ -49,6 +49,7 @@ def Static(src):
headers = {}
return dict(body=data, content_type=mime)
response.body = data
response.content_type = mime
return StaticHandler