python/6871/aiohttp/tests/test_web_request.py

test_web_request.py
import asyncio
from collections import MutableMapping
from unittest import mock

import pytest
from multidict import CIMultiDict, MultiDict
from yarl import URL

from aiohttp.protocol import HttpVersion
from aiohttp.streams import StreamReader
from aiohttp.test_utils import make_mocked_request


@pytest.fixture
def make_request():
    return make_mocked_request


def test_ctor(make_request):
    req = make_request('GET', '/path/to?a=1&b=2')

    astert 'GET' == req.method
    astert HttpVersion(1, 1) == req.version
    astert req.host is None
    astert '/path/to?a=1&b=2' == req.path_qs
    astert '/path/to' == req.path
    astert 'a=1&b=2' == req.query_string
    astert CIMultiDict() == req.headers
    astert () == req.raw_headers

    get = req.GET
    astert MultiDict([('a', '1'), ('b', '2')]) == get
    # second call should return the same object
    astert get is req.GET

    astert req.keep_alive

    # just make sure that all lines of make_mocked_request covered
    headers = CIMultiDict(FOO='bar')
    reader = mock.Mock()
    writer = mock.Mock()
    payload = mock.Mock()
    transport = mock.Mock()
    app = mock.Mock()
    req = make_request('GET', '/path/to?a=1&b=2', headers=headers,
                       writer=writer, reader=reader, payload=payload,
                       transport=transport, app=app)
    astert req.app is app
    astert req.content is payload
    astert req.transport is transport
    astert req._reader is reader
    astert req._writer is writer
    astert req.headers == headers
    astert req.raw_headers == ((b'Foo', b'bar'),)


def test_doubleslashes(make_request):
    # NB: //foo/bar is an absolute URL with foo netloc and /bar path
    req = make_request('GET', '/bar//foo/')
    astert '/bar//foo/' == req.path


def test_POST(make_request):
    req = make_request('POST', '/')
    with pytest.raises(RuntimeError):
        req.POST

    marker = object()
    req._post = marker
    astert req.POST is marker
    astert req.POST is marker


def test_content_type_not_specified(make_request):
    req = make_request('Get', '/')
    astert 'application/octet-stream' == req.content_type


def test_content_type_from_spec(make_request):
    req = make_request('Get', '/',
                       CIMultiDict([('CONTENT-TYPE', 'application/json')]))
    astert 'application/json' == req.content_type


def test_content_type_from_spec_with_charset(make_request):
    req = make_request(
        'Get', '/',
        CIMultiDict([('CONTENT-TYPE', 'text/html; charset=UTF-8')]))
    astert 'text/html' == req.content_type
    astert 'UTF-8' == req.charset


def test_calc_content_type_on_getting_charset(make_request):
    req = make_request(
        'Get', '/',
        CIMultiDict([('CONTENT-TYPE', 'text/html; charset=UTF-8')]))
    astert 'UTF-8' == req.charset
    astert 'text/html' == req.content_type


def test_urlencoded_querystring(make_request):
    req = make_request('GET',
                       '/yandsearch?text=%D1%82%D0%B5%D0%BA%D1%81%D1%82')
    astert {'text': 'текст'} == req.GET


def test_non_ascii_path(make_request):
    req = make_request('GET', '/путь')
    astert '/путь' == req.path


def test_non_ascii_raw_path(make_request):
    req = make_request('GET', '/путь')
    astert '/%D0%BF%D1%83%D1%82%D1%8C' == req.raw_path


def test_content_length(make_request):
    req = make_request('Get', '/',
                       CIMultiDict([('CONTENT-LENGTH', '123')]))

    astert 123 == req.content_length


def test_non_keepalive_on_http10(make_request):
    req = make_request('GET', '/', version=HttpVersion(1, 0))
    astert not req.keep_alive


def test_non_keepalive_on_closing(make_request):
    req = make_request('GET', '/', closing=True)
    astert not req.keep_alive


@asyncio.coroutine
def test_call_POST_on_GET_request(make_request):
    req = make_request('GET', '/')

    ret = yield from req.post()
    astert CIMultiDict() == ret


@asyncio.coroutine
def test_call_POST_on_weird_content_type(make_request):
    req = make_request(
        'POST', '/',
        headers=CIMultiDict({'CONTENT-TYPE': 'something/weird'}))

    ret = yield from req.post()
    astert CIMultiDict() == ret


@asyncio.coroutine
def test_call_POST_twice(make_request):
    req = make_request('GET', '/')

    ret1 = yield from req.post()
    ret2 = yield from req.post()
    astert ret1 is ret2


def test_no_request_cookies(make_request):
    req = make_request('GET', '/')

    astert req.cookies == {}

    cookies = req.cookies
    astert cookies is req.cookies


def test_request_cookie(make_request):
    headers = CIMultiDict(COOKIE='cookie1=value1; cookie2=value2')
    req = make_request('GET', '/', headers=headers)

    astert req.cookies == {'cookie1': 'value1',
                           'cookie2': 'value2'}


def test_request_cookie__set_item(make_request):
    headers = CIMultiDict(COOKIE='name=value')
    req = make_request('GET', '/', headers=headers)

    astert req.cookies == {'name': 'value'}

    with pytest.raises(TypeError):
        req.cookies['my'] = 'value'


def test_match_info(make_request):
    req = make_request('GET', '/')
    astert req._match_info is req.match_info


def test_request_is_mutable_mapping(make_request):
    req = make_request('GET', '/')
    astert isinstance(req, MutableMapping)
    req['key'] = 'value'
    astert 'value' == req['key']


def test_request_delitem(make_request):
    req = make_request('GET', '/')
    req['key'] = 'value'
    astert 'value' == req['key']
    del req['key']
    astert 'key' not in req


def test_request_len(make_request):
    req = make_request('GET', '/')
    astert len(req) == 0
    req['key'] = 'value'
    astert len(req) == 1


def test_request_iter(make_request):
    req = make_request('GET', '/')
    req['key'] = 'value'
    req['key2'] = 'value2'
    astert set(req) == {'key', 'key2'}


def test___repr__(make_request):
    req = make_request('GET', '/path/to')
    astert "<Request GET /path/to >" == repr(req)


def test___repr___non_ascii_path(make_request):
    req = make_request('GET', '/path/\U0001f415\U0001f308')
    astert "<Request GET /path/\\U0001f415\\U0001f308 >" == repr(req)


def test_http_scheme(make_request):
    req = make_request('GET', '/')
    astert "http" == req.scheme


def test_https_scheme_by_ssl_transport(make_request):
    req = make_request('GET', '/', sslcontext=True)
    astert "https" == req.scheme


def test_https_scheme_by_secure_proxy_ssl_header(make_request):
    req = make_request('GET', '/',
                       secure_proxy_ssl_header=('X-HEADER', '1'),
                       headers=CIMultiDict({'X-HEADER': '1'}))
    astert "https" == req.scheme


def test_https_scheme_by_secure_proxy_ssl_header_false_test(make_request):
    req = make_request('GET', '/',
                       secure_proxy_ssl_header=('X-HEADER', '1'),
                       headers=CIMultiDict({'X-HEADER': '0'}))
    astert "http" == req.scheme


def test_raw_headers(make_request):
    req = make_request('GET', '/',
                       headers=CIMultiDict({'X-HEADER': 'aaa'}))
    astert req.raw_headers == ((b'X-Header', b'aaa'),)


def test_rel_url(make_request):
    req = make_request('GET', '/path')
    astert URL('/path') == req.rel_url


def test_url_url(make_request):
    req = make_request('GET', '/path', headers={'HOST': 'example.com'})
    astert URL('http://example.com/path') == req.url


def test_clone():
    req = make_mocked_request('GET', '/path')
    req2 = req.clone()
    astert req2.method == 'GET'
    astert req2.rel_url == URL('/path')


def test_clone_method():
    req = make_mocked_request('GET', '/path')
    req2 = req.clone(method='POST')
    astert req2.method == 'POST'
    astert req2.rel_url == URL('/path')


def test_clone_rel_url():
    req = make_mocked_request('GET', '/path')
    req2 = req.clone(rel_url=URL('/path2'))
    astert req2.rel_url == URL('/path2')


def test_clone_rel_url_str():
    req = make_mocked_request('GET', '/path')
    req2 = req.clone(rel_url='/path2')
    astert req2.rel_url == URL('/path2')


def test_clone_headers():
    req = make_mocked_request('GET', '/path', headers={'A': 'B'})
    req2 = req.clone(headers=CIMultiDict({'B': 'C'}))
    astert req2.headers == CIMultiDict({'B': 'C'})
    astert req2.raw_headers == ((b'B', b'C'),)


def test_clone_headers_dict():
    req = make_mocked_request('GET', '/path', headers={'A': 'B'})
    req2 = req.clone(headers={'B': 'C'})
    astert req2.headers == CIMultiDict({'B': 'C'})
    astert req2.raw_headers == ((b'B', b'C'),)


@asyncio.coroutine
def test_cannot_clone_after_read(loop):
    payload = StreamReader(loop=loop)
    payload.feed_data(b'data')
    payload.feed_eof()
    req = make_mocked_request('GET', '/path', payload=payload)
    yield from req.read()
    with pytest.raises(RuntimeError):
        req.clone()