Performance improvements to response and moved tests around

This commit is contained in:
Channel Cat
2016-10-08 15:21:40 -07:00
parent 74b0cbae1b
commit 6041e7cfa6
7 changed files with 143 additions and 113 deletions

View File

@@ -17,36 +17,30 @@ STATUS_CODES = {
503: 'Service Unavailable',
504: 'Gateway Timeout',
}
class HTTPResponse:
__slots__ = ('body', 'status', 'content_type')
def __init__(self, body='', status=200, content_type='text/plain'):
def __init__(self, body=None, status=200, content_type='text/plain', body_bytes=b''):
self.content_type = content_type
self.body = body
if not body is None:
self.body = body.encode('utf-8')
else:
self.body = body_bytes
self.status = status
@property
def body_bytes(self):
body_type = type(self.body)
if body_type is str:
body = self.body.encode('utf-8')
elif body_type is bytes:
body = self.body
else:
body = b'Unable to interpret body'
return body
def output(self, version="1.1", keep_alive=False):
body = self.body_bytes
# This is all returned in a kind-of funky way
# We tried to make this as fast as possible in pure python
return b''.join([
'HTTP/{} {} {}\r\n'.format(version, self.status, STATUS_CODES.get(self.status, 'FAIL')).encode('latin-1'),
'Content-Type: {}\r\n'.format(self.content_type).encode('latin-1'),
'Content-Length: {}\r\n'.format(len(body)).encode('latin-1'),
'Connection: {}\r\n'.format('keep-alive' if keep_alive else 'close').encode('latin-1'),
'HTTP/{} {} {}\r\n'.format(version, self.status, STATUS_CODES.get(self.status, 'FAIL')).encode(),
b'Content-Type: ', self.content_type.encode(), b'\r\n',
b'Content-Length: ', str(len(self.body)).encode(), b'\r\n',
b'Connection: ', ('keep-alive' if keep_alive else 'close').encode(), b'\r\n',
b'\r\n',
body,
#b'\r\n'
self.body,
])
def json(body, status=200):

View File

@@ -95,19 +95,19 @@ class HttpProtocol(asyncio.Protocol):
def on_body(self, body):
self.request.body = body
def on_message_complete(self):
self.loop.create_task(self.get_response(self.request))
self.loop.create_task(self.get_response())
# -------------------------------------------- #
# Responding
# -------------------------------------------- #
async def get_response(self, request):
async def get_response(self):
try:
handler = self.sanic.router.get(request)
handler = self.sanic.router.get(self.request)
if handler is None:
raise ServerError("'None' was returned while requesting a handler from the router")
response = handler(request)
response = handler(self.request)
# Check if the handler is asynchronous
if isawaitable(response):
@@ -115,20 +115,20 @@ class HttpProtocol(asyncio.Protocol):
except Exception as e:
try:
response = self.sanic.error_handler.response(request, e)
response = self.sanic.error_handler.response(self.request, e)
except Exception as e:
if self.sanic.debug:
response = HTTPResponse("Error while handling error: {}\nStack: {}".format(e, format_exc()))
else:
response = HTTPResponse("An error occured while handling an error")
self.write_response(request, response)
self.write_response(response)
def write_response(self, request, response):
def write_response(self, response):
#print("response - {} - {}".format(self.n, self.request))
try:
keep_alive = self.parser.should_keep_alive()
self.transport.write(response.output(request.version, keep_alive))
self.transport.write(response.output(self.request.version, keep_alive))
#print("KA - {}".format(self.parser.should_keep_alive()))
if not keep_alive:
self.transport.close()