improve performance
This commit is contained in:
parent
4e8aac4b41
commit
8b23dec322
17
sanic/app.py
17
sanic/app.py
|
@ -13,7 +13,7 @@ from sanic.constants import HTTP_METHODS
|
||||||
from sanic.exceptions import ServerError, URLBuildError, SanicException
|
from sanic.exceptions import ServerError, URLBuildError, SanicException
|
||||||
from sanic.handlers import ErrorHandler
|
from sanic.handlers import ErrorHandler
|
||||||
from sanic.log import log
|
from sanic.log import log
|
||||||
from sanic.response import HTTPResponse
|
from sanic.response import HTTPResponse, StreamingHTTPResponse
|
||||||
from sanic.router import Router
|
from sanic.router import Router
|
||||||
from sanic.server import serve, serve_multiple, HttpProtocol
|
from sanic.server import serve, serve_multiple, HttpProtocol
|
||||||
from sanic.static import register as static_register
|
from sanic.static import register as static_register
|
||||||
|
@ -342,14 +342,17 @@ class Sanic:
|
||||||
def converted_response_type(self, response):
|
def converted_response_type(self, response):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def handle_request(self, request, response_callback):
|
async def handle_request(self, request, write_callback, stream_callback):
|
||||||
"""Take a request from the HTTP Server and return a response object
|
"""Take a request from the HTTP Server and return a response object
|
||||||
to be sent back The HTTP Server only expects a response object, so
|
to be sent back The HTTP Server only expects a response object, so
|
||||||
exception handling must be done here
|
exception handling must be done here
|
||||||
|
|
||||||
:param request: HTTP Request object
|
:param request: HTTP Request object
|
||||||
:param response_callback: Response function to be called with the
|
:param write_callback: Synchronous response function to be
|
||||||
response as the only argument
|
called with the response as the only argument
|
||||||
|
:param stream_callback: Coroutine that handles streaming a
|
||||||
|
StreamingHTTPResponse if produced by the handler.
|
||||||
|
|
||||||
:return: Nothing
|
:return: Nothing
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
|
@ -416,7 +419,11 @@ class Sanic:
|
||||||
response = HTTPResponse(
|
response = HTTPResponse(
|
||||||
"An error occurred while handling an error")
|
"An error occurred while handling an error")
|
||||||
|
|
||||||
await response_callback(response)
|
# pass the response to the correct callback
|
||||||
|
if isinstance(response, StreamingHTTPResponse):
|
||||||
|
await stream_callback(response)
|
||||||
|
else:
|
||||||
|
write_callback(response)
|
||||||
|
|
||||||
# -------------------------------------------------------------------- #
|
# -------------------------------------------------------------------- #
|
||||||
# Testing
|
# Testing
|
||||||
|
|
|
@ -162,27 +162,61 @@ class HttpProtocol(asyncio.Protocol):
|
||||||
self.request.body = b''.join(self.request.body)
|
self.request.body = b''.join(self.request.body)
|
||||||
|
|
||||||
self._request_handler_task = self.loop.create_task(
|
self._request_handler_task = self.loop.create_task(
|
||||||
self.request_handler(self.request, self.write_response))
|
self.request_handler(
|
||||||
|
self.request,
|
||||||
|
self.write_response,
|
||||||
|
self.stream_response))
|
||||||
|
|
||||||
# -------------------------------------------- #
|
# -------------------------------------------- #
|
||||||
# Responding
|
# Responding
|
||||||
# -------------------------------------------- #
|
# -------------------------------------------- #
|
||||||
async def write_response(self, response):
|
def write_response(self, response):
|
||||||
|
"""
|
||||||
|
Writes response content synchronously to the transport.
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
keep_alive = (
|
keep_alive = (
|
||||||
self.parser.should_keep_alive() and not self.signal.stopped)
|
self.parser.should_keep_alive() and not self.signal.stopped)
|
||||||
|
|
||||||
if isinstance(response, StreamingHTTPResponse):
|
self.transport.write(
|
||||||
# streaming responses should have direct write access to the
|
response.output(
|
||||||
# transport
|
self.request.version, keep_alive,
|
||||||
response.transport = self.transport
|
self.request_timeout))
|
||||||
await response.stream(
|
except AttributeError:
|
||||||
self.request.version, keep_alive, self.request_timeout)
|
log.error(
|
||||||
|
('Invalid response object for url {}, '
|
||||||
|
'Expected Type: HTTPResponse, Actual Type: {}').format(
|
||||||
|
self.url, type(response)))
|
||||||
|
self.write_error(ServerError('Invalid response type'))
|
||||||
|
except RuntimeError:
|
||||||
|
log.error(
|
||||||
|
'Connection lost before response written @ {}'.format(
|
||||||
|
self.request.ip))
|
||||||
|
except Exception as e:
|
||||||
|
self.bail_out(
|
||||||
|
"Writing response failed, connection closed {}".format(
|
||||||
|
repr(e)))
|
||||||
|
finally:
|
||||||
|
if not keep_alive:
|
||||||
|
self.transport.close()
|
||||||
else:
|
else:
|
||||||
self.transport.write(
|
self._last_request_time = current_time
|
||||||
response.output(
|
self.cleanup()
|
||||||
self.request.version, keep_alive,
|
|
||||||
self.request_timeout))
|
async def stream_response(self, response):
|
||||||
|
"""
|
||||||
|
Streams a response to the client asynchronously. Attaches
|
||||||
|
the transport to the response so the response consumer can
|
||||||
|
write to the response as needed.
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
keep_alive = (
|
||||||
|
self.parser.should_keep_alive() and not self.signal.stopped)
|
||||||
|
|
||||||
|
response.transport = self.transport
|
||||||
|
await response.stream(
|
||||||
|
self.request.version, keep_alive, self.request_timeout)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
log.error(
|
log.error(
|
||||||
('Invalid response object for url {}, '
|
('Invalid response object for url {}, '
|
||||||
|
|
Loading…
Reference in New Issue
Block a user