WIP - Split RequestTimeout, ResponseTimout, and KeepAliveTimeout into different timeouts, with different callbacks.
This commit is contained in:
@@ -1,38 +1,97 @@
|
||||
from json import JSONDecodeError
|
||||
from sanic import Sanic
|
||||
import asyncio
|
||||
from sanic.response import text
|
||||
from sanic.exceptions import RequestTimeout
|
||||
from sanic.config import Config
|
||||
import aiohttp
|
||||
from aiohttp import TCPConnector
|
||||
from sanic.testing import SanicTestClient, HOST, PORT
|
||||
|
||||
|
||||
class DelayableTCPConnector(TCPConnector):
|
||||
class DelayableHttpRequest(object):
|
||||
def __new__(cls, req, delay):
|
||||
cls = super(DelayableTCPConnector.DelayableHttpRequest, cls).\
|
||||
__new__(cls)
|
||||
cls.req = req
|
||||
cls.delay = delay
|
||||
return cls
|
||||
|
||||
def __getattr__(self, item):
|
||||
return getattr(self.req, item)
|
||||
|
||||
def send(self, *args, **kwargs):
|
||||
if self.delay and self.delay > 0:
|
||||
_ = yield from asyncio.sleep(self.delay)
|
||||
self.req.send(*args, **kwargs)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
_post_connect_delay = kwargs.pop('post_connect_delay', 0)
|
||||
_pre_request_delay = kwargs.pop('pre_request_delay', 0)
|
||||
super(DelayableTCPConnector, self).__init__(*args, **kwargs)
|
||||
self._post_connect_delay = _post_connect_delay
|
||||
self._pre_request_delay = _pre_request_delay
|
||||
|
||||
@asyncio.coroutine
|
||||
def connect(self, req):
|
||||
req = DelayableTCPConnector.\
|
||||
DelayableHttpRequest(req, self._pre_request_delay)
|
||||
conn = yield from super(DelayableTCPConnector, self).connect(req)
|
||||
if self._post_connect_delay and self._post_connect_delay > 0:
|
||||
_ = yield from asyncio.sleep(self._post_connect_delay)
|
||||
return conn
|
||||
|
||||
|
||||
class DelayableSanicTestClient(SanicTestClient):
|
||||
def __init__(self, app, request_delay=1):
|
||||
super(DelayableSanicTestClient, self).__init__(app)
|
||||
self._request_delay = request_delay
|
||||
|
||||
async def _local_request(self, method, uri, cookies=None, *args,
|
||||
**kwargs):
|
||||
if uri.startswith(('http:', 'https:', 'ftp:', 'ftps://' '//')):
|
||||
url = uri
|
||||
else:
|
||||
url = 'http://{host}:{port}{uri}'.format(
|
||||
host=HOST, port=PORT, uri=uri)
|
||||
|
||||
conn = DelayableTCPConnector(pre_request_delay=self._request_delay,
|
||||
verify_ssl=False)
|
||||
async with aiohttp.ClientSession(
|
||||
cookies=cookies, connector=conn) as session:
|
||||
# Insert a delay after creating the connection
|
||||
# But before sending the request.
|
||||
|
||||
async with getattr(session, method.lower())(
|
||||
url, *args, **kwargs) as response:
|
||||
try:
|
||||
response.text = await response.text()
|
||||
except UnicodeDecodeError:
|
||||
response.text = None
|
||||
|
||||
try:
|
||||
response.json = await response.json()
|
||||
except (JSONDecodeError,
|
||||
UnicodeDecodeError,
|
||||
aiohttp.ClientResponseError):
|
||||
response.json = None
|
||||
|
||||
response.body = await response.read()
|
||||
return response
|
||||
|
||||
|
||||
Config.REQUEST_TIMEOUT = 1
|
||||
request_timeout_app = Sanic('test_request_timeout')
|
||||
request_timeout_default_app = Sanic('test_request_timeout_default')
|
||||
|
||||
|
||||
@request_timeout_app.route('/1')
|
||||
async def handler_1(request):
|
||||
await asyncio.sleep(2)
|
||||
return text('OK')
|
||||
|
||||
|
||||
@request_timeout_app.exception(RequestTimeout)
|
||||
def handler_exception(request, exception):
|
||||
return text('Request Timeout from error_handler.', 408)
|
||||
|
||||
|
||||
def test_server_error_request_timeout():
|
||||
request, response = request_timeout_app.test_client.get('/1')
|
||||
assert response.status == 408
|
||||
assert response.text == 'Request Timeout from error_handler.'
|
||||
|
||||
|
||||
@request_timeout_default_app.route('/1')
|
||||
async def handler_2(request):
|
||||
await asyncio.sleep(2)
|
||||
async def handler(request):
|
||||
return text('OK')
|
||||
|
||||
|
||||
def test_default_server_error_request_timeout():
|
||||
request, response = request_timeout_default_app.test_client.get('/1')
|
||||
client = DelayableSanicTestClient(request_timeout_default_app, 2)
|
||||
request, response = client.get('/1')
|
||||
assert response.status == 408
|
||||
assert response.text == 'Error: Request Timeout'
|
||||
|
||||
Reference in New Issue
Block a user