# passerelle - uniform access to multiple data sources and services # Copyright (C) 2023 Entr'ouvert # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU Affero General Public License as published # by the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . import pytest import responses import responses.matchers import tests.utils from passerelle.apps.proxy.models import Resource @pytest.fixture def proxy(db): return tests.utils.setup_access_rights( Resource.objects.create(slug='echo', upstream_base_url='https://example.org/') ) @pytest.fixture def endpoint(proxy): return tests.utils.generic_endpoint_url('proxy', 'request', slug=proxy.slug) @pytest.fixture def mocked_responses(): with responses.RequestsMock(assert_all_requests_are_fired=False) as rsp: yield rsp def test_get(mocked_responses, app, proxy, endpoint): mocked_responses.get( url='https://example.org/foo/bar', body='ok', match=[ responses.matchers.query_string_matcher(''), ], ) resp = app.get(endpoint + '/foo/bar', status=200) assert resp.text == 'ok' def test_status(mocked_responses, app, proxy, endpoint): mocked_responses.get(url='https://example.org/foo/bar', body='bad request', status=400) resp = app.get(endpoint + '/foo/bar', status=400) assert resp.text == 'bad request' def test_post(mocked_responses, app, proxy, endpoint): mocked_responses.post( url='https://example.org/post', body='ok', match=[ responses.matchers.json_params_matcher({'foo': 'bar'}), ], ) resp = app.post_json(endpoint + '/post', params={'foo': 'bar'}, status=200) assert resp.text == 'ok' def no_header_matcher(header_name): def inner(request): if header_name in request.headers: return False, f'Found header "{header_name} in requests headers.' return True, None return inner def test_headers(mocked_responses, app, proxy, endpoint): mocked_responses.get( url='https://example.org/foo/bar', body='ok', match=[ responses.matchers.header_matcher({'User-Agent': 'test-ua'}), no_header_matcher('x-foo'), no_header_matcher('dontpass'), ], ) resp = app.get(endpoint + '/foo/bar', headers={'user-agent': 'test-ua', 'dontpass': 'x'}, status=200) assert resp.text == 'ok' def test_forced_headers(mocked_responses, app, proxy, endpoint): proxy.forced_headers = ''' x-foo : bar badentry # comment: do not use me ''' proxy.save() mocked_responses.get( url='https://example.org/foo/bar', body='ok', match=[ responses.matchers.header_matcher({'x-foo': 'bar'}), no_header_matcher('dontpass'), ], ) resp = app.get(endpoint + '/foo/bar', headers={'user-agent': 'test', 'dontpass': 'x'}, status=200) assert resp.text == 'ok' def test_query_parameters(mocked_responses, app, proxy, endpoint): mocked_responses.get( url='https://example.org/foo/bar', body='ok', match=[ responses.matchers.query_param_matcher({'param1': '1', 'param2': '2'}, strict_match=True), ], ) resp = app.get(endpoint + '/foo/bar?param1=1¶m2=2', status=200) assert resp.text == 'ok' def test_publik_signature_is_removed(mocked_responses, app, proxy, endpoint): mocked_responses.get( url='https://example.org/foo/bar', body='ok', match=[ responses.matchers.query_param_matcher({'param1': '1', 'param2': '2'}, strict_match=True), ], ) resp = app.get( endpoint + '/foo/bar?param1=1¶m2=2&orig=coucou&algo=foo&nonce=bar×tamp=xxx&signature=okok', status=200, ) assert resp.text == 'ok' def test_auth(mocked_responses, app, proxy, endpoint): proxy.basic_auth_username = 'test-login' proxy.basic_auth_password = 'test-pass' proxy.save() mocked_responses.get( url='https://example.org/foo/bar', body='ok', match=[responses.matchers.header_matcher({'Authorization': 'Basic dGVzdC1sb2dpbjp0ZXN0LXBhc3M='})], ) resp = app.get(endpoint + '/foo/bar', status=200) assert resp.text == 'ok' def test_timeout(mocked_responses, app, proxy, endpoint): proxy.http_timeout = 5 proxy.save() mocked_responses.get( url='https://example.org/foo/bar', body='ok', match=[responses.matchers.request_kwargs_matcher({'timeout': 5})], ) resp = app.get(endpoint + '/foo/bar', status=200) assert resp.text == 'ok'