Change Payload Too Large process

When Payload Too Large occurs, it uses error handler.
This commit is contained in:
38elements 2016-12-04 10:50:32 +09:00
parent 80af9e6d76
commit 662e0c9965
3 changed files with 75 additions and 9 deletions

View File

@ -34,6 +34,10 @@ class RequestTimeout(SanicException):
status_code = 408 status_code = 408
class PayloadTooLarge(SanicException):
status_code = 413
class Handler: class Handler:
handlers = None handlers = None

View File

@ -14,7 +14,7 @@ except ImportError:
from .log import log from .log import log
from .request import Request from .request import Request
from .exceptions import RequestTimeout from .exceptions import RequestTimeout, PayloadTooLarge
class Signal: class Signal:
@ -81,9 +81,8 @@ class HttpProtocol(asyncio.Protocol):
else: else:
if self._request_handler_task: if self._request_handler_task:
self._request_handler_task.cancel() self._request_handler_task.cancel()
response = self.error_handler.response( exception = RequestTimeout('Request Timeout')
self.request, RequestTimeout('Request Timeout')) self.write_error(exception)
self.write_response(response)
# -------------------------------------------- # # -------------------------------------------- #
# Parsing # Parsing
@ -94,9 +93,8 @@ class HttpProtocol(asyncio.Protocol):
# memory limits # memory limits
self._total_request_size += len(data) self._total_request_size += len(data)
if self._total_request_size > self.request_max_size: if self._total_request_size > self.request_max_size:
return self.bail_out( exception = PayloadTooLarge('Payload Too Large')
"Request too large ({}), connection closed".format( self.write_error(exception)
self._total_request_size))
# Create parser if this is the first time we're receiving data # Create parser if this is the first time we're receiving data
if self.parser is None: if self.parser is None:
@ -116,8 +114,8 @@ class HttpProtocol(asyncio.Protocol):
def on_header(self, name, value): def on_header(self, name, value):
if name == b'Content-Length' and int(value) > self.request_max_size: if name == b'Content-Length' and int(value) > self.request_max_size:
return self.bail_out( exception = PayloadTooLarge('Payload Too Large')
"Request body too large ({}), connection closed".format(value)) self.write_error(exception)
self.headers.append((name.decode(), value.decode('utf-8'))) self.headers.append((name.decode(), value.decode('utf-8')))
@ -164,6 +162,16 @@ class HttpProtocol(asyncio.Protocol):
self.bail_out( self.bail_out(
"Writing response failed, connection closed {}".format(e)) "Writing response failed, connection closed {}".format(e))
def write_error(self, exception):
try:
response = self.error_handler.response(self.request, exception)
version = self.request.version if self.request else '1.1'
self.transport.write(response.output(version))
self.transport.close()
except Exception as e:
self.bail_out(
"Writing error failed, connection closed {}".format(e))
def bail_out(self, message): def bail_out(self, message):
log.debug(message) log.debug(message)
self.transport.close() self.transport.close()

View File

@ -0,0 +1,54 @@
from sanic import Sanic
from sanic.response import text
from sanic.exceptions import PayloadTooLarge
from sanic.utils import sanic_endpoint_test
data_received_app = Sanic('data_received')
data_received_app.config.REQUEST_MAX_SIZE = 1
data_received_default_app = Sanic('data_received_default')
data_received_default_app.config.REQUEST_MAX_SIZE = 1
on_header_default_app = Sanic('on_header')
on_header_default_app.config.REQUEST_MAX_SIZE = 500
@data_received_app.route('/1')
async def handler1(request):
return text('OK')
@data_received_app.exception(PayloadTooLarge)
def handler_exception(request, exception):
return text('Payload Too Large from error_handler.', 413)
def test_payload_too_large_from_error_handler():
response = sanic_endpoint_test(
data_received_app, uri='/1', gather_request=False)
assert response.status == 413
assert response.text == 'Payload Too Large from error_handler.'
@data_received_default_app.route('/1')
async def handler2(request):
return text('OK')
def test_payload_too_large_at_data_received_default():
response = sanic_endpoint_test(
data_received_default_app, uri='/1', gather_request=False)
assert response.status == 413
assert response.text == 'Error: Payload Too Large'
@on_header_default_app.route('/1')
async def handler3(request):
return text('OK')
def test_payload_too_large_at_on_header_default():
data = 'a' * 1000
response = sanic_endpoint_test(
on_header_default_app, method='post', uri='/1',
gather_request=False, data=data)
assert response.status == 413
assert response.text == 'Error: Payload Too Large'