def setup_method(self, method): asgi = self._item.callspec.getparam('asgi') self.qs = 'marker=deadbeef&limit=10' self.headers = { 'Content-Type': 'text/plain', 'Content-Length': '4829', 'Authorization': '' } self.root_path = '/test' self.path = '/hello' self.relative_uri = self.path + '?' + self.qs self.req = create_req(asgi, root_path=self.root_path, port=8080, path='/hello', query_string=self.qs, headers=self.headers) self.req_noqs = create_req(asgi, root_path=self.root_path, path='/hello', headers=self.headers)
def test_attribute_headers(self, asgi, name, value, attr, default): headers = {name: value} req = create_req(asgi, headers=headers) assert getattr(req, attr) == value req = create_req(asgi) assert getattr(req, attr) == default
def test_uri_https(self, asgi): # ======================================================= # Default port, implicit # ======================================================= req = create_req( asgi, path='/hello', scheme='https') uri = ('https://' + testing.DEFAULT_HOST + '/hello') assert req.uri == uri # ======================================================= # Default port, explicit # ======================================================= req = create_req( asgi, path='/hello', scheme='https', port=443) uri = ('https://' + testing.DEFAULT_HOST + '/hello') assert req.uri == uri # ======================================================= # Non-default port # ======================================================= req = create_req( asgi, path='/hello', scheme='https', port=22) uri = ('https://' + testing.DEFAULT_HOST + ':22/hello') assert req.uri == uri
def test_relative_uri(self, asgi): assert self.req.relative_uri == self.root_path + self.relative_uri assert self.req_noqs.relative_uri == self.root_path + self.path req_noapp = create_req(asgi, path='/hello', query_string=self.qs, headers=self.headers) assert req_noapp.relative_uri == self.relative_uri req_noapp = create_req(asgi, path='/hello/', query_string=self.qs, headers=self.headers) relative_trailing_uri = self.path + '/?' + self.qs # NOTE(kgriffs): Call twice to check caching works assert req_noapp.relative_uri == relative_trailing_uri assert req_noapp.relative_uri == relative_trailing_uri options = RequestOptions() options.strip_url_path_trailing_slash = False req_noapp = create_req(asgi, options=options, path='/hello/', query_string=self.qs, headers=self.headers) assert req_noapp.relative_uri == '/hello/' + '?' + self.qs
def test_content_length(self, asgi): headers = {'content-length': '5656'} req = create_req(asgi, headers=headers) assert req.content_length == 5656 headers = {'content-length': ''} req = create_req(asgi, headers=headers) assert req.content_length is None
def test_x_real_ip(asgi): req = create_req(asgi, host='example.com', path='/access_route', headers={'X-Real-IP': '2001:db8:cafe::17'}) assert req.access_route == ['2001:db8:cafe::17', '127.0.0.1']
def test_scheme_http(self, asgi, http_version, set_forwarded_proto): scheme = 'http' forwarded_scheme = 'HttPs' headers = dict(self.headers) if set_forwarded_proto: headers['X-Forwarded-Proto'] = forwarded_scheme req = create_req( asgi, http_version=http_version, scheme=scheme, root_path=self.root_path, path='/hello', query_string=self.qs, headers=headers) assert req.scheme == scheme assert req.port == 80 if set_forwarded_proto: assert req.forwarded_scheme == forwarded_scheme.lower() else: assert req.forwarded_scheme == scheme
def test_good_path(asgi, uri_prefix, uri_path, expected_path, mtype, monkeypatch): monkeypatch.setattr(io, 'open', lambda path, mode: io.BytesIO(path.encode())) sr = create_sr(asgi, uri_prefix, '/var/www/statics') req_path = uri_prefix[:-1] if uri_prefix.endswith('/') else uri_prefix req_path += uri_path req = _util.create_req(asgi, host='test.com', path=req_path, root_path='statics') resp = _util.create_resp(asgi) if asgi: async def run(): await sr(req, resp) return await resp.stream.read() body = testing.invoke_coroutine_sync(run) else: sr(req, resp) body = resp.stream.read() assert resp.content_type == mtype assert body.decode() == '/var/www/statics' + expected_path
def test_good_path(asgi, uri_prefix, uri_path, expected_path, mtype, monkeypatch): monkeypatch.setattr(io, 'open', lambda path, mode: io.BytesIO(path.encode())) sr = create_sr(asgi, uri_prefix, '/var/www/statics') req_path = uri_prefix[:-1] if uri_prefix.endswith('/') else uri_prefix req_path += uri_path req = _util.create_req(asgi, host='test.com', path=req_path, root_path='statics') resp = _util.create_resp(asgi) if asgi: async def run(): await sr(req, resp) return await resp.stream.read() body = falcon.async_to_sync(run) else: sr(req, resp) body = resp.stream.read() assert resp.content_type in _MIME_ALTERNATIVE.get(mtype, (mtype, )) assert body.decode() == os.path.normpath('/var/www/statics' + expected_path)
def test_rfc_forwarded(asgi): req = create_req( asgi, host='example.com', path='/access_route', headers={ 'Forwarded': ( 'for=192.0.2.43,for=,' 'for="[2001:db8:cafe::17]:555",' 'for=x,' 'for="unknown", by=_hidden,for="\\"\\\\",' 'for="_don\\"t_\\try_this\\\\at_home_\\42",' 'for="198\\.51\\.100\\.17\\:1236";' 'proto=https;host=example.com' ) }, ) compares = [ '192.0.2.43', '2001:db8:cafe::17', 'x', 'unknown', '"\\', '_don"t_try_this\\at_home_42', '198.51.100.17', '127.0.0.1', ] assert req.access_route == compares # test cached assert req.access_route == compares
def test_pathlib_path(asgi, patch_open): patch_open() sr = create_sr(asgi, '/static/', pathlib.Path('/var/www/statics')) req_path = '/static/css/test.css' req = _util.create_req(asgi, host='test.com', path=req_path, root_path='statics') resp = _util.create_resp(asgi) if asgi: async def run(): await sr(req, resp) return await resp.stream.read() body = falcon.async_to_sync(run) else: sr(req, resp) body = resp.stream.read() assert body.decode() == os.path.normpath('/var/www/statics/css/test.css')
def test_forwarded_host(asgi): req = create_req( asgi, host='suchproxy02.suchtesting.com', path='/languages', headers={ 'Forwarded': 'host=something.org , host=suchproxy01.suchtesting.com' }, ) assert req.forwarded is not None for f in req.forwarded: assert f.src is None assert f.dest is None assert f.scheme is None assert req.forwarded[0].host == 'something.org' assert req.forwarded[1].host == 'suchproxy01.suchtesting.com' assert req.forwarded_host == 'something.org' assert req.forwarded_scheme == 'http' assert req.forwarded_uri != req.uri assert req.forwarded_uri == 'http://something.org/languages' assert req.forwarded_prefix == 'http://something.org'
def test_good_path(asgi, uri_prefix, uri_path, expected_path, mtype, patch_open): patch_open() sr = create_sr(asgi, uri_prefix, '/var/www/statics') req_path = uri_prefix[:-1] if uri_prefix.endswith('/') else uri_prefix req_path += uri_path req = _util.create_req(asgi, host='test.com', path=req_path, root_path='statics') resp = _util.create_resp(asgi) if asgi: async def run(): await sr(req, resp) return await resp.stream.read() body = falcon.async_to_sync(run) else: sr(req, resp) body = resp.stream.read() assert resp.content_type in _MIME_ALTERNATIVE.get(mtype, (mtype, )) assert body.decode() == os.path.normpath('/var/www/statics' + expected_path) assert resp.headers.get('accept-ranges') == 'bytes'
def test_forwarded_multiple_params(asgi): req = create_req( asgi, host='suchproxy02.suchtesting.com', path='/languages', headers={ 'Forwarded': ('host=something.org;proto=hTTps;ignore=me;for=108.166.30.185, ' 'by=203.0.113.43;host=suchproxy01.suchtesting.com;proto=httP') }) assert req.forwarded is not None assert req.forwarded[0].host == 'something.org' assert req.forwarded[0].scheme == 'https' assert req.forwarded[0].src == '108.166.30.185' assert req.forwarded[0].dest is None assert req.forwarded[1].host == 'suchproxy01.suchtesting.com' assert req.forwarded[1].scheme == 'http' assert req.forwarded[1].src is None assert req.forwarded[1].dest == '203.0.113.43' assert req.forwarded_scheme == 'https' assert req.forwarded_host == 'something.org' assert req.forwarded_uri != req.uri assert req.forwarded_uri == 'https://something.org/languages' assert req.forwarded_prefix == 'https://something.org'
def test_date(self, asgi, header, attr): date = datetime.datetime(2013, 4, 4, 5, 19, 18) date_str = 'Thu, 04 Apr 2013 05:19:18 GMT' headers = {header: date_str} req = create_req(asgi, headers=headers) assert getattr(req, attr) == date
def test_range_unit(self, asgi): headers = {'Range': 'bytes=10-'} req = create_req(asgi, headers=headers) assert req.range == (10, -1) assert req.range_unit == 'bytes' headers = {'Range': 'items=10-'} req = create_req(asgi, headers=headers) assert req.range == (10, -1) assert req.range_unit == 'items' headers = {'Range': ''} req = create_req(asgi, headers=headers) with pytest.raises(falcon.HTTPInvalidHeader): req.range_unit req = create_req(asgi) assert req.range_unit is None
def test_netloc_default_port(self, asgi, http_version): req = create_req(asgi, http_version=http_version, root_path=self.root_path, path='/hello', query_string=self.qs, headers=self.headers) assert req.netloc == 'falconframework.org'
def test_malformed_rfc_forwarded(asgi): req = create_req( asgi, host='example.com', path='/access_route', headers={'Forwarded': 'for'} ) assert req.access_route == ['127.0.0.1'] # test cached assert req.access_route == ['127.0.0.1']
def test_remote_addr(asgi, remote_addr): req = create_req( asgi, host='example.com', path='/access_route', remote_addr=remote_addr, ) assert req.access_route == [remote_addr]
def test_forwarded_quote_escaping(asgi): req = create_req( asgi, host='suchproxy02.suchtesting.com', path='/languages', root_path='doge', headers={'Forwarded': 'for="1\\.2\\.3\\.4";some="extra,\\"info\\""'}) assert req.forwarded[0].host is None assert req.forwarded[0].src == '1.2.3.4'
def test_no_forwarded_headers(asgi): req = create_req(asgi, host='example.com', path='/languages', root_path='backoffice') assert req.forwarded is None assert req.forwarded_uri == req.uri assert req.forwarded_uri == 'http://example.com/backoffice/languages' assert req.forwarded_prefix == 'http://example.com/backoffice'
def _test_error_details(self, headers, attr_name, error_type, title, description, asgi): req = create_req(asgi, headers=headers) try: getattr(req, attr_name) pytest.fail('{} not raised'.format(error_type.__name__)) except error_type as ex: assert ex.title == title assert ex.description == description
def test_escape_malformed_requests(forwarded, expected_dest, asgi): req = create_req(asgi, host='suchproxy02.suchtesting.com', path='/languages', root_path='doge', headers={'Forwarded': forwarded}) assert len(req.forwarded) == 1 assert req.forwarded[0].src == '1.2.3.4' assert req.forwarded[0].dest == expected_dest
def test_x_forwarded_proto(asgi): req = create_req(asgi, host='example.org', path='/languages', headers={'X-Forwarded-Proto': 'HTTPS'}) assert req.forwarded is None assert req.forwarded_scheme == 'https' assert req.forwarded_uri != req.uri assert req.forwarded_uri == 'https://example.org/languages' assert req.forwarded_prefix == 'https://example.org'
def test_port_explicit(self, asgi, http_version): port = 9000 req = create_req(asgi, http_version=http_version, port=port, root_path=self.root_path, path='/hello', query_string=self.qs, headers=self.headers) assert req.port == port
def test_x_forwarded_host(asgi): req = create_req(asgi, host='suchproxy.suchtesting.com', path='/languages', headers={'X-Forwarded-Host': 'something.org'}) assert req.forwarded is None assert req.forwarded_host == 'something.org' assert req.forwarded_uri != req.uri assert req.forwarded_uri == 'http://something.org/languages' assert req.forwarded_prefix == 'http://something.org' assert req.forwarded_prefix == 'http://something.org' # Check cached value
def test_scheme_https(self, asgi, http_version): scheme = 'https' req = create_req(asgi, http_version=http_version, scheme=scheme, root_path=self.root_path, path='/hello', query_string=self.qs, headers=self.headers) assert req.scheme == scheme assert req.port == 443
def test_client_prefers(self, asgi): headers = {'Accept': 'application/xml'} req = create_req(asgi, headers=headers) preferred_type = req.client_prefers(['application/xml']) assert preferred_type == 'application/xml' headers = {'Accept': '*/*'} preferred_type = req.client_prefers( ('application/xml', 'application/json')) # NOTE(kgriffs): If client doesn't care, "prefer" the first one assert preferred_type == 'application/xml' headers = {'Accept': 'text/*; q=0.1, application/xhtml+xml; q=0.5'} req = create_req(asgi, headers=headers) preferred_type = req.client_prefers(['application/xhtml+xml']) assert preferred_type == 'application/xhtml+xml' headers = {'Accept': '3p12845j;;;asfd;'} req = create_req(asgi, headers=headers) preferred_type = req.client_prefers(['application/xhtml+xml']) assert preferred_type is None
def test_remote_addr_only(asgi): req = create_req(asgi, host='example.com', path='/access_route', headers={ 'Forwarded': ('for=192.0.2.43, for="[2001:db8:cafe::17]:555",' 'for="unknown", by=_hidden,for="\\"\\\\",' 'for="198\\.51\\.100\\.17\\:1236";' 'proto=https;host=example.com') }) assert req.remote_addr == '127.0.0.1'
def test_fallback_filename(asgi, uri, default, expected, content_type, downloadable, patch_open, monkeypatch): def validate(path): if os.path.normpath(default) not in path: raise IOError() patch_open(validate=validate) monkeypatch.setattr('os.path.isfile', lambda file: os.path.normpath(default) in file) sr = create_sr( asgi, '/static', '/var/www/statics', downloadable=downloadable, fallback_filename=default, ) req_path = '/static/' + uri req = _util.create_req(asgi, host='test.com', path=req_path, root_path='statics') resp = _util.create_resp(asgi) if asgi: async def run(): await sr(req, resp) return await resp.stream.read() body = falcon.async_to_sync(run) else: sr(req, resp) body = resp.stream.read() assert sr.match(req.path) expected_content = os.path.normpath( os.path.join('/var/www/statics', expected)) assert body.decode() == expected_content assert resp.content_type in _MIME_ALTERNATIVE.get(content_type, (content_type, )) assert resp.headers.get('accept-ranges') == 'bytes' if downloadable: assert os.path.basename(expected) in resp.downloadable_as else: assert resp.downloadable_as is None