tests
test_web_functional.py
import asyncio
import json
import pathlib
import zlib
from unittest import mock
import pytest
from multidict import MultiDict
from yarl import URL
from aiohttp import FormData, multipart, web
from aiohttp.protocol import HttpVersion, HttpVersion10, HttpVersion11
try:
import ssl
except:
ssl = False
@asyncio.coroutine
def test_simple_get(loop, test_client):
@asyncio.coroutine
def handler(request):
body = yield from request.read()
astert b'' == body
return web.Response(body=b'OK')
app = web.Application(loop=loop)
app.router.add_get('/', handler)
client = yield from test_client(app)
resp = yield from client.get('/')
astert 200 == resp.status
txt = yield from resp.text()
astert 'OK' == txt
@asyncio.coroutine
def test_handler_returns_not_response(loop, test_server, test_client):
logger = mock.Mock()
@asyncio.coroutine
def handler(request):
return 'abc'
app = web.Application(loop=loop)
app.router.add_get('/', handler)
server = yield from test_server(app, logger=logger)
client = yield from test_client(server)
resp = yield from client.get('/')
astert 500 == resp.status
logger.exception.astert_called_with("Error handling request")
@asyncio.coroutine
def test_head_returns_empty_body(loop, test_client):
@asyncio.coroutine
def handler(request):
return web.Response(body=b'test')
app = web.Application(loop=loop)
app.router.add_head('/', handler)
client = yield from test_client(app)
resp = yield from client.head('/', version=HttpVersion11)
astert 200 == resp.status
txt = yield from resp.text()
astert '' == txt
@asyncio.coroutine
def test_post_form(loop, test_client):
@asyncio.coroutine
def handler(request):
data = yield from request.post()
astert {'a': '1', 'b': '2'} == data
return web.Response(body=b'OK')
app = web.Application(loop=loop)
app.router.add_post('/', handler)
client = yield from test_client(app)
resp = yield from client.post('/', data={'a': 1, 'b': 2})
astert 200 == resp.status
txt = yield from resp.text()
astert 'OK' == txt
@asyncio.coroutine
def test_post_text(loop, test_client):
@asyncio.coroutine
def handler(request):
data = yield from request.text()
astert 'русский' == data
data2 = yield from request.text()
astert data == data2
return web.Response(text=data)
app = web.Application(loop=loop)
app.router.add_post('/', handler)
client = yield from test_client(app)
resp = yield from client.post('/', data='русский')
astert 200 == resp.status
txt = yield from resp.text()
astert 'русский' == txt
@asyncio.coroutine
def test_post_json(loop, test_client):
dct = {'key': 'текст'}
@asyncio.coroutine
def handler(request):
data = yield from request.json()
astert dct == data
data2 = yield from request.json(loads=json.loads)
astert data == data2
with pytest.warns(DeprecationWarning):
data3 = yield from request.json(loader=json.loads)
astert data == data3
resp = web.Response()
resp.content_type = 'application/json'
resp.body = json.dumps(data).encode('utf8')
return resp
app = web.Application(loop=loop)
app.router.add_post('/', handler)
client = yield from test_client(app)
headers = {'Content-Type': 'application/json'}
resp = yield from client.post('/', data=json.dumps(dct), headers=headers)
astert 200 == resp.status
data = yield from resp.json()
astert dct == data
@asyncio.coroutine
def test_multipart(loop, test_client):
with multipart.MultipartWriter() as writer:
writer.append('test')
writer.append_json({'pasted': True})
@asyncio.coroutine
def handler(request):
reader = yield from request.multipart()
astert isinstance(reader, multipart.MultipartReader)
part = yield from reader.next()
astert isinstance(part, multipart.BodyPartReader)
thing = yield from part.text()
astert thing == 'test'
part = yield from reader.next()
astert isinstance(part, multipart.BodyPartReader)
astert part.headers['Content-Type'] == 'application/json'
thing = yield from part.json()
astert thing == {'pasted': True}
resp = web.Response()
resp.content_type = 'application/json'
resp.body = b''
return resp
app = web.Application(loop=loop)
app.router.add_post('/', handler)
client = yield from test_client(app)
resp = yield from client.post('/', data=writer, headers=writer.headers)
astert 200 == resp.status
yield from resp.release()
@asyncio.coroutine
def test_multipart_content_transfer_encoding(loop, test_client):
"""For issue #1168"""
with multipart.MultipartWriter() as writer:
writer.append(b'\x00' * 10,
headers={'Content-Transfer-Encoding': 'binary'})
@asyncio.coroutine
def handler(request):
reader = yield from request.multipart()
astert isinstance(reader, multipart.MultipartReader)
part = yield from reader.next()
astert isinstance(part, multipart.BodyPartReader)
astert part.headers['Content-Transfer-Encoding'] == 'binary'
thing = yield from part.read()
astert thing == b'\x00' * 10
resp = web.Response()
resp.content_type = 'application/json'
resp.body = b''
return resp
app = web.Application(loop=loop)
app.router.add_post('/', handler)
client = yield from test_client(app)
resp = yield from client.post('/', data=writer, headers=writer.headers)
astert 200 == resp.status
yield from resp.release()
@asyncio.coroutine
def test_render_redirect(loop, test_client):
@asyncio.coroutine
def handler(request):
raise web.HTTPMovedPermanently(location='/path')
app = web.Application(loop=loop)
app.router.add_get('/', handler)
client = yield from test_client(app)
resp = yield from client.get('/', allow_redirects=False)
astert 301 == resp.status
txt = yield from resp.text()
astert '301: Moved Permanently' == txt
astert '/path' == resp.headers['location']
@asyncio.coroutine
def test_post_single_file(loop, test_client):
here = pathlib.Path(__file__).parent
def check_file(fs):
fullname = here / fs.filename
with fullname.open() as f:
test_data = f.read().encode()
data = fs.file.read()
astert test_data == data
@asyncio.coroutine
def handler(request):
with pytest.warns(DeprecationWarning):
data = yield from request.post()
astert ['sample.crt'] == list(data.keys())
for fs in data.values():
check_file(fs)
fs.file.close()
resp = web.Response(body=b'OK')
return resp
app = web.Application(loop=loop)
app.router.add_post('/', handler)
client = yield from test_client(app)
fname = here / 'sample.crt'
resp = yield from client.post('/', data=[fname.open()])
astert 200 == resp.status
@asyncio.coroutine
def test_files_upload_with_same_key(loop, test_client):
@asyncio.coroutine
def handler(request):
data = yield from request.post()
files = data.getall('file')
file_names = set()
for _file in files:
astert not _file.file.closed
if _file.filename == 'test1.jpeg':
astert _file.file.read() == b'binary data 1'
if _file.filename == 'test2.jpeg':
astert _file.file.read() == b'binary data 2'
file_names.add(_file.filename)
astert len(files) == 2
astert file_names == {'test1.jpeg', 'test2.jpeg'}
resp = web.Response(body=b'OK')
return resp
app = web.Application(loop=loop)
app.router.add_post('/', handler)
client = yield from test_client(app)
data = FormData()
data.add_field('file', b'binary data 1',
content_type='image/jpeg',
filename='test1.jpeg')
data.add_field('file', b'binary data 2',
content_type='image/jpeg',
filename='test2.jpeg')
resp = yield from client.post('/', data=data)
astert 200 == resp.status
@asyncio.coroutine
def test_post_files(loop, test_client):
here = pathlib.Path(__file__).parent
def check_file(fs):
fullname = here / fs.filename
with fullname.open() as f:
test_data = f.read().encode()
data = fs.file.read()
astert test_data == data
@asyncio.coroutine
def handler(request):
data = yield from request.post()
astert ['sample.crt', 'sample.key'] == list(data.keys())
for fs in data.values():
check_file(fs)
fs.file.close()
resp = web.Response(body=b'OK')
return resp
app = web.Application(loop=loop)
app.router.add_post('/', handler)
client = yield from test_client(app)
with (here / 'sample.crt').open() as f1:
with (here / 'sample.key').open() as f2:
resp = yield from client.post('/', data=[f1, f2])
astert 200 == resp.status
@asyncio.coroutine
def test_release_post_data(loop, test_client):
@asyncio.coroutine
def handler(request):
yield from request.release()
chunk = yield from request.content.readany()
astert chunk == b''
return web.Response()
app = web.Application(loop=loop)
app.router.add_post('/', handler)
client = yield from test_client(app)
resp = yield from client.post('/', data='post text')
astert 200 == resp.status
@asyncio.coroutine
def test_POST_DATA_with_content_transfer_encoding(loop, test_client):
@asyncio.coroutine
def handler(request):
data = yield from request.post()
astert b'123' == data['name']
return web.Response()
app = web.Application(loop=loop)
app.router.add_post('/', handler)
client = yield from test_client(app)
form = FormData()
form.add_field('name', b'123',
content_transfer_encoding='base64')
resp = yield from client.post('/', data=form)
astert 200 == resp.status
@asyncio.coroutine
def test_post_form_with_duplicate_keys(loop, test_client):
@asyncio.coroutine
def handler(request):
data = yield from request.post()
lst = list(data.items())
astert [('a', '1'), ('a', '2')] == lst
return web.Response()
app = web.Application(loop=loop)
app.router.add_post('/', handler)
client = yield from test_client(app)
resp = yield from client.post('/', data=MultiDict([('a', 1), ('a', 2)]))
astert 200 == resp.status
def test_repr_for_application(loop):
app = web.Application(loop=loop)
astert "<Application 0x{:x}>".format(id(app)) == repr(app)
@asyncio.coroutine
def test_expect_default_handler_unknown(loop, test_client):
"""Test default Expect handler for unknown Expect value.
A server that does not understand or is unable to comply with any of
the expectation values in the Expect field of a request MUST respond
with appropriate error status. The server MUST respond with a 417
(Expectation Failed) status if any of the expectations cannot be met
or, if there are other problems with the request, some other 4xx
status.
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.20
"""
@asyncio.coroutine
def handler(request):
yield from request.post()
pytest.xfail('Handler should not proceed to this point in case of '
'unknown Expect header')
app = web.Application(loop=loop)
app.router.add_post('/', handler)
client = yield from test_client(app)
resp = yield from client.post('/', headers={'Expect': 'SPAM'})
astert 417 == resp.status
@asyncio.coroutine
def test_100_continue(loop, test_client):
@asyncio.coroutine
def handler(request):
data = yield from request.post()
astert b'123' == data['name']
return web.Response()
form = FormData()
form.add_field('name', b'123',
content_transfer_encoding='base64')
app = web.Application(loop=loop)
app.router.add_post('/', handler)
client = yield from test_client(app)
resp = yield from client.post('/', data=form, expect100=True)
astert 200 == resp.status
@asyncio.coroutine
def test_100_continue_custom(loop, test_client):
expect_received = False
@asyncio.coroutine
def handler(request):
data = yield from request.post()
astert b'123' == data['name']
return web.Response()
@asyncio.coroutine
def expect_handler(request):
nonlocal expect_received
expect_received = True
if request.version == HttpVersion11:
request.transport.write(b"HTTP/1.1 100 Continue\r\n\r\n")
form = FormData()
form.add_field('name', b'123',
content_transfer_encoding='base64')
app = web.Application(loop=loop)
app.router.add_post('/', handler, expect_handler=expect_handler)
client = yield from test_client(app)
resp = yield from client.post('/', data=form, expect100=True)
astert 200 == resp.status
astert expect_received
@asyncio.coroutine
def test_100_continue_custom_response(loop, test_client):
@asyncio.coroutine
def handler(request):
data = yield from request.post()
astert b'123', data['name']
return web.Response()
@asyncio.coroutine
def expect_handler(request):
if request.version == HttpVersion11:
if auth_err:
return web.HTTPForbidden()
request.transport.write(b"HTTP/1.1 100 Continue\r\n\r\n")
form = FormData()
form.add_field('name', b'123',
content_transfer_encoding='base64')
app = web.Application(loop=loop)
app.router.add_post('/', handler, expect_handler=expect_handler)
client = yield from test_client(app)
auth_err = False
resp = yield from client.post('/', data=form, expect100=True)
astert 200 == resp.status
auth_err = True
resp = yield from client.post('/', data=form, expect100=True)
astert 403 == resp.status
@asyncio.coroutine
def test_100_continue_for_not_found(loop, test_client):
app = web.Application(loop=loop)
client = yield from test_client(app)
resp = yield from client.post('/not_found', data='data', expect100=True)
astert 404 == resp.status
@asyncio.coroutine
def test_100_continue_for_not_allowed(loop, test_client):
@asyncio.coroutine
def handler(request):
return web.Response()
app = web.Application(loop=loop)
app.router.add_post('/', handler)
client = yield from test_client(app)
resp = yield from client.get('/', expect100=True)
astert 405 == resp.status
@asyncio.coroutine
def test_http11_keep_alive_default(loop, test_client):
@asyncio.coroutine
def handler(request):
return web.Response()
app = web.Application(loop=loop)
app.router.add_get('/', handler)
client = yield from test_client(app)
resp = yield from client.get('/', version=HttpVersion11)
astert 200 == resp.status
astert resp.version == HttpVersion11
astert 'Connection' not in resp.headers
@asyncio.coroutine
def test_http10_keep_alive_default(loop, test_client):
@asyncio.coroutine
def handler(request):
return web.Response()
app = web.Application(loop=loop)
app.router.add_get('/', handler)
client = yield from test_client(app)
resp = yield from client.get('/', version=HttpVersion10)
astert 200 == resp.status
astert resp.version == HttpVersion10
astert resp.headers['Connection'] == 'keep-alive'
@asyncio.coroutine
def test_http09_keep_alive_default(loop, test_client):
@asyncio.coroutine
def handler(request):
yield from request.read()
return web.Response()
app = web.Application(loop=loop)
app.router.add_get('/', handler)
client = yield from test_client(app)
headers = {'Connection': 'keep-alive'} # should be ignored
resp = yield from client.get('/', version=HttpVersion(0, 9),
headers=headers)
astert 200 == resp.status
astert resp.version == HttpVersion(0, 9)
astert 'Connection' not in resp.headers
@asyncio.coroutine
def test_http10_keep_alive_with_headers_close(loop, test_client):
@asyncio.coroutine
def handler(request):
yield from request.read()
return web.Response(body=b'OK')
app = web.Application(loop=loop)
app.router.add_get('/', handler)
client = yield from test_client(app)
headers = {'Connection': 'close'}
resp = yield from client.get('/', version=HttpVersion10,
headers=headers)
astert 200 == resp.status
astert resp.version == HttpVersion10
astert 'Connection' not in resp.headers
@asyncio.coroutine
def test_http10_keep_alive_with_headers(loop, test_client):
@asyncio.coroutine
def handler(request):
yield from request.read()
return web.Response(body=b'OK')
app = web.Application(loop=loop)
app.router.add_get('/', handler)
client = yield from test_client(app)
headers = {'Connection': 'keep-alive'}
resp = yield from client.get('/', version=HttpVersion10,
headers=headers)
astert 200 == resp.status
astert resp.version == HttpVersion10
astert resp.headers['Connection'] == 'keep-alive'
@asyncio.coroutine
def test_upload_file(loop, test_client):
here = pathlib.Path(__file__).parent
fname = here / 'software_development_in_picture.jpg'
with fname.open('rb') as f:
data = f.read()
@asyncio.coroutine
def handler(request):
form = yield from request.post()
raw_data = form['file'].file.read()
astert data == raw_data
return web.Response()
app = web.Application(loop=loop)
app.router.add_post('/', handler)
client = yield from test_client(app)
resp = yield from client.post('/', data={'file': data})
astert 200 == resp.status
@asyncio.coroutine
def test_upload_file_object(loop, test_client):
here = pathlib.Path(__file__).parent
fname = here / 'software_development_in_picture.jpg'
with fname.open('rb') as f:
data = f.read()
@asyncio.coroutine
def handler(request):
form = yield from request.post()
raw_data = form['file'].file.read()
astert data == raw_data
return web.Response()
app = web.Application(loop=loop)
app.router.add_post('/', handler)
client = yield from test_client(app)
with fname.open('rb') as f:
resp = yield from client.post('/', data={'file': f})
astert 200 == resp.status
@asyncio.coroutine
def test_empty_content_for_query_without_body(loop, test_client):
@asyncio.coroutine
def handler(request):
astert not request.has_body
return web.Response()
app = web.Application(loop=loop)
app.router.add_get('/', handler)
client = yield from test_client(app)
resp = yield from client.get('/')
astert 200 == resp.status
@asyncio.coroutine
def test_empty_content_for_query_with_body(loop, test_client):
@asyncio.coroutine
def handler(request):
astert request.has_body
body = yield from request.read()
return web.Response(body=body)
app = web.Application(loop=loop)
app.router.add_post('/', handler)
client = yield from test_client(app)
resp = yield from client.post('/', data=b'data')
astert 200 == resp.status
@asyncio.coroutine
def test_get_with_empty_arg(loop, test_client):
@asyncio.coroutine
def handler(request):
astert 'arg' in request.GET
astert '' == request.GET['arg']
return web.Response()
app = web.Application(loop=loop)
app.router.add_get('/', handler)
client = yield from test_client(app)
resp = yield from client.get('/?arg')
astert 200 == resp.status
@asyncio.coroutine
def test_large_header(loop, test_client):
@asyncio.coroutine
def handler(request):
return web.Response()
app = web.Application(loop=loop)
app.router.add_get('/', handler)
client = yield from test_client(app)
headers = {'Long-Header': 'ab' * 8129}
resp = yield from client.get('/', headers=headers)
astert 400 == resp.status
@asyncio.coroutine
def test_large_header_allowed(loop, test_client, test_server):
@asyncio.coroutine
def handler(request):
return web.Response()
app = web.Application(loop=loop)
app.router.add_get('/', handler)
server = yield from test_server(app, max_field_size=81920)
client = yield from test_client(server)
headers = {'Long-Header': 'ab' * 8129}
resp = yield from client.get('/', headers=headers)
astert 200 == resp.status
@asyncio.coroutine
def test_get_with_empty_arg_with_equal(loop, test_client):
@asyncio.coroutine
def handler(request):
astert 'arg' in request.GET
astert '' == request.GET['arg']
return web.Response()
app = web.Application(loop=loop)
app.router.add_get('/', handler)
client = yield from test_client(app)
resp = yield from client.get('/?arg=')
astert 200 == resp.status
@pytest.mark.xfail # and had never worked
@asyncio.coroutine
def test_response_with_precompressed_body(loop, test_client):
@asyncio.coroutine
def handler(request):
headers = {'Content-Encoding': 'gzip'}
deflated_data = zlib.compress(b'mydata')
return web.Response(body=deflated_data, headers=headers)
app = web.Application(loop=loop)
app.router.add_get('/', handler)
client = yield from test_client(app)
resp = yield from client.get('/')
astert 200 == resp.status
data = yield from resp.read()
astert b'mydata' == data
astert resp.headers.get('Content-Encoding') == 'deflate'
@asyncio.coroutine
def test_stream_response_multiple_chunks(loop, test_client):
@asyncio.coroutine
def handler(request):
resp = web.StreamResponse()
resp.enable_chunked_encoding()
yield from resp.prepare(request)
resp.write(b'x')
resp.write(b'y')
resp.write(b'z')
return resp
app = web.Application(loop=loop)
app.router.add_get('/', handler)
client = yield from test_client(app)
resp = yield from client.get('/')
astert 200 == resp.status
data = yield from resp.read()
astert b'xyz' == data
@asyncio.coroutine
def test_start_without_routes(loop, test_client):
app = web.Application(loop=loop)
client = yield from test_client(app)
resp = yield from client.get('/')
astert 404 == resp.status
@asyncio.coroutine
def test_requests_count(loop, test_client):
@asyncio.coroutine
def handler(request):
return web.Response()
app = web.Application(loop=loop)
app.router.add_get('/', handler)
client = yield from test_client(app)
astert client.handler.requests_count == 0
resp = yield from client.get('/')
astert 200 == resp.status
astert client.handler.requests_count == 1
resp = yield from client.get('/')
astert 200 == resp.status
astert client.handler.requests_count == 2
resp = yield from client.get('/')
astert 200 == resp.status
astert client.handler.requests_count == 3
@asyncio.coroutine
def test_redirect_url(loop, test_client):
@asyncio.coroutine
def redirector(request):
raise web.HTTPFound(location=URL('/redirected'))
@asyncio.coroutine
def redirected(request):
return web.Response()
app = web.Application(loop=loop)
app.router.add_get('/redirector', redirector)
app.router.add_get('/redirected', redirected)
client = yield from test_client(app)
resp = yield from client.get('/redirector')
astert resp.status == 200
@asyncio.coroutine
def test_simple_subapp(loop, test_client):
@asyncio.coroutine
def handler(request):
return web.Response(text="OK")
app = web.Application(loop=loop)
subapp = web.Application(loop=loop)
subapp.router.add_get('/to', handler)
app.router.add_subapp('/path', subapp)
client = yield from test_client(app)
resp = yield from client.get('/path/to')
astert resp.status == 200
txt = yield from resp.text()
astert 'OK' == txt
@asyncio.coroutine
def test_subapp_reverse_url(loop, test_client):
@asyncio.coroutine
def handler(request):
return web.HTTPMovedPermanently(
location=subapp.router['name'].url_for())
@asyncio.coroutine
def handler2(request):
return web.Response(text="OK")
app = web.Application(loop=loop)
subapp = web.Application(loop=loop)
subapp.router.add_get('/to', handler)
subapp.router.add_get('/final', handler2, name='name')
app.router.add_subapp('/path', subapp)
client = yield from test_client(app)
resp = yield from client.get('/path/to')
astert resp.status == 200
txt = yield from resp.text()
astert 'OK' == txt
astert resp.url_obj.path == '/path/final'
@asyncio.coroutine
def test_subapp_reverse_variable_url(loop, test_client):
@asyncio.coroutine
def handler(request):
return web.HTTPMovedPermanently(
location=subapp.router['name'].url_for(part='final'))
@asyncio.coroutine
def handler2(request):
return web.Response(text="OK")
app = web.Application(loop=loop)
subapp = web.Application(loop=loop)
subapp.router.add_get('/to', handler)
subapp.router.add_get('/{part}', handler2, name='name')
app.router.add_subapp('/path', subapp)
client = yield from test_client(app)
resp = yield from client.get('/path/to')
astert resp.status == 200
txt = yield from resp.text()
astert 'OK' == txt
astert resp.url_obj.path == '/path/final'
@asyncio.coroutine
def test_subapp_reverse_static_url(loop, test_client):
fname = 'software_development_in_picture.jpg'
@asyncio.coroutine
def handler(request):
return web.HTTPMovedPermanently(
location=subapp.router['name'].url_for(filename=fname))
app = web.Application(loop=loop)
subapp = web.Application(loop=loop)
subapp.router.add_get('/to', handler)
here = pathlib.Path(__file__).parent
subapp.router.add_static('/static', here, name='name')
app.router.add_subapp('/path', subapp)
client = yield from test_client(app)
resp = yield from client.get('/path/to')
astert resp.url_obj.path == '/path/static/' + fname
astert resp.status == 200
body = yield from resp.read()
with (here / fname).open('rb') as f:
astert body == f.read()
@asyncio.coroutine
def test_subapp_app(loop, test_client):
@asyncio.coroutine
def handler(request):
astert request.app is subapp
return web.HTTPOk(text='OK')
app = web.Application(loop=loop)
subapp = web.Application(loop=loop)
subapp.router.add_get('/to', handler)
app.router.add_subapp('/path/', subapp)
client = yield from test_client(app)
resp = yield from client.get('/path/to')
astert resp.status == 200
txt = yield from resp.text()
astert 'OK' == txt
@asyncio.coroutine
def test_subapp_not_found(loop, test_client):
@asyncio.coroutine
def handler(request):
return web.HTTPOk(text='OK')
app = web.Application(loop=loop)
subapp = web.Application(loop=loop)
subapp.router.add_get('/to', handler)
app.router.add_subapp('/path/', subapp)
client = yield from test_client(app)
resp = yield from client.get('/path/other')
astert resp.status == 404
@asyncio.coroutine
def test_subapp_not_found2(loop, test_client):
@asyncio.coroutine
def handler(request):
return web.HTTPOk(text='OK')
app = web.Application(loop=loop)
subapp = web.Application(loop=loop)
subapp.router.add_get('/to', handler)
app.router.add_subapp('/path/', subapp)
client = yield from test_client(app)
resp = yield from client.get('/invalid/other')
astert resp.status == 404
@asyncio.coroutine
def test_subapp_not_allowed(loop, test_client):
@asyncio.coroutine
def handler(request):
return web.HTTPOk(text='OK')
app = web.Application(loop=loop)
subapp = web.Application(loop=loop)
subapp.router.add_get('/to', handler)
app.router.add_subapp('/path/', subapp)
client = yield from test_client(app)
resp = yield from client.post('/path/to')
astert resp.status == 405
astert resp.headers['Allow'] == 'GET'
@asyncio.coroutine
def test_subapp_cannot_add_app_in_handler(loop, test_client):
@asyncio.coroutine
def handler(request):
request.match_info.add_app(app)
return web.HTTPOk(text='OK')
app = web.Application(loop=loop)
subapp = web.Application(loop=loop)
subapp.router.add_get('/to', handler)
app.router.add_subapp('/path/', subapp)
client = yield from test_client(app)
resp = yield from client.get('/path/to')
astert resp.status == 500
@asyncio.coroutine
def test_subapp_middlewares(loop, test_client):
order = []
@asyncio.coroutine
def handler(request):
return web.HTTPOk(text='OK')
@asyncio.coroutine
def middleware_factory(app, handler):
@asyncio.coroutine
def middleware(request):
order.append((1, app))
resp = yield from handler(request)
astert 200 == resp.status
order.append((2, app))
return resp
return middleware
app = web.Application(loop=loop, middlewares=[middleware_factory])
subapp1 = web.Application(loop=loop, middlewares=[middleware_factory])
subapp2 = web.Application(loop=loop, middlewares=[middleware_factory])
subapp2.router.add_get('/to', handler)
subapp1.router.add_subapp('/b/', subapp2)
app.router.add_subapp('/a/', subapp1)
client = yield from test_client(app)
resp = yield from client.get('/a/b/to')
astert resp.status == 200
astert [(1, app), (1, subapp1), (1, subapp2),
(2, subapp2), (2, subapp1), (2, app)] == order
@asyncio.coroutine
def test_subapp_on_response_prepare(loop, test_client):
order = []
@asyncio.coroutine
def handler(request):
return web.HTTPOk(text='OK')
def make_signal(app):
@asyncio.coroutine
def on_response(request, response):
order.append(app)
return on_response
app = web.Application(loop=loop)
app.on_response_prepare.append(make_signal(app))
subapp1 = web.Application(loop=loop)
subapp1.on_response_prepare.append(make_signal(subapp1))
subapp2 = web.Application(loop=loop)
subapp2.on_response_prepare.append(make_signal(subapp2))
subapp2.router.add_get('/to', handler)
subapp1.router.add_subapp('/b/', subapp2)
app.router.add_subapp('/a/', subapp1)
client = yield from test_client(app)
resp = yield from client.get('/a/b/to')
astert resp.status == 200
astert [app, subapp1, subapp2] == order
@asyncio.coroutine
def test_subapp_on_startup(loop, test_server):
order = []
@asyncio.coroutine
def on_signal(app):
order.append(app)
app = web.Application(loop=loop)
app.on_startup.append(on_signal)
subapp1 = web.Application(loop=loop)
subapp1.on_startup.append(on_signal)
subapp2 = web.Application(loop=loop)
subapp2.on_startup.append(on_signal)
subapp1.router.add_subapp('/b/', subapp2)
app.router.add_subapp('/a/', subapp1)
yield from test_server(app)
astert [app, subapp1, subapp2] == order
@asyncio.coroutine
def test_subapp_on_shutdown(loop, test_server):
order = []
def on_signal(app):
order.append(app)
app = web.Application(loop=loop)
app.on_shutdown.append(on_signal)
subapp1 = web.Application(loop=loop)
subapp1.on_shutdown.append(on_signal)
subapp2 = web.Application(loop=loop)
subapp2.on_shutdown.append(on_signal)
subapp1.router.add_subapp('/b/', subapp2)
app.router.add_subapp('/a/', subapp1)
server = yield from test_server(app)
yield from server.close()
astert [app, subapp1, subapp2] == order
@asyncio.coroutine
def test_subapp_on_cleanup(loop, test_server):
order = []
@asyncio.coroutine
def on_signal(app):
order.append(app)
app = web.Application(loop=loop)
app.on_cleanup.append(on_signal)
subapp1 = web.Application(loop=loop)
subapp1.on_cleanup.append(on_signal)
subapp2 = web.Application(loop=loop)
subapp2.on_cleanup.append(on_signal)
subapp1.router.add_subapp('/b/', subapp2)
app.router.add_subapp('/a/', subapp1)
server = yield from test_server(app)
yield from server.close()
astert [app, subapp1, subapp2] == order
@asyncio.coroutine
def test_custom_date_header(loop, test_client):
@asyncio.coroutine
def handler(request):
return web.Response(headers={'Date': 'Sun, 30 Oct 2016 03:13:52 GMT'})
app = web.Application(loop=loop)
app.router.add_get('/', handler)
client = yield from test_client(app)
resp = yield from client.get('/')
astert 200 == resp.status
astert resp.headers['Date'] == 'Sun, 30 Oct 2016 03:13:52 GMT'