Projet

Général

Profil

0001-allow-cookies-usage-in-endpoint-requests-27654.patch

Emmanuel Cazenave, 01 novembre 2018 13:37

Télécharger (6,29 ko)

Voir les différences:

Subject: [PATCH] allow cookies usage in endpoint requests (#27654)

 passerelle/utils/__init__.py   |  9 +++++++--
 passerelle/views.py            |  2 ++
 tests/test_generic_endpoint.py | 30 ++++++++++++++++++++++++++++++
 tests/test_requests.py         | 25 +++++++++++++++++++++++++
 tests/utils.py                 |  4 ++--
 5 files changed, 66 insertions(+), 4 deletions(-)
passerelle/utils/__init__.py
214 214
        if 'timeout' not in kwargs:
215 215
            kwargs['timeout'] = settings.REQUESTS_TIMEOUT
216 216

  
217
        # don't use persistent cookies
218
        self.cookies.clear()
217
        # persist cookie for the endpoint duration
218
        if self.resource and hasattr(self.resource, 'cookiejar'):
219
            self.cookies = self.resource.cookiejar
219 220

  
220 221
        response = super(Request, self).request(method, url, **kwargs)
221 222

  
223
        if getattr(self, 'cookies', None) and self.resource \
224
           and hasattr(self.resource, 'cookiejar'):
225
            self.resource.cookiejar = self.cookies
226

  
222 227
        if method == 'GET' and cache_duration and (response.status_code // 100 == 2):
223 228
            cache.set(cache_key, {
224 229
                'content': response.content,
passerelle/views.py
22 22
from django.utils.encoding import force_text
23 23
from django.forms.models import modelform_factory
24 24
from django.forms.widgets import ClearableFileInput
25
import requests
25 26

  
26 27
from dateutil import parser as date_parser
27 28

  
......
287 288
    def dispatch(self, request, *args, **kwargs):
288 289
        self.init_stuff(request, *args, **kwargs)
289 290
        connector = self.get_object()
291
        connector.cookiejar = requests.cookies.cookiejar_from_dict({})
290 292
        self.endpoint = None
291 293
        endpoints = []
292 294
        for name, method in inspect.getmembers(connector):
tests/test_generic_endpoint.py
295 295
    assert cache.get_calls == 5
296 296
    assert cache.set_calls == 3
297 297
    assert resp1.json_body != resp6.json_body
298

  
299

  
300
def test_endpoint_cookies(app, db, monkeypatch):
301

  
302
    @endpoint(methods=['get'])
303
    def httpcall(obj, request):
304
        headers = {'Set-Cookie': 'somecookie=somecookievalue'}
305
        with utils.mock_url('http://some.example.org/', 'ok', headers):
306
            response = obj.requests.get('http://some.example.org/')
307
            cookie1 = response.request.headers.get('Cookie')
308
            response = obj.requests.get('http://some.example.org/')
309
            cookie2 = response.request.headers.get('Cookie')
310
            return {
311
                'cookie1': cookie1,
312
                'cookie2': cookie2
313
            }
314

  
315
    monkeypatch.setattr(StubInvoicesConnector, 'httpcall', httpcall, raising=False)
316

  
317
    connector = StubInvoicesConnector(slug='fake')
318
    connector.save()
319

  
320
    json_res = app.get('/stub-invoices/fake/httpcall').json
321
    assert json_res['cookie1'] is None
322
    assert json_res['cookie2'] == 'somecookie=somecookievalue'
323
    # Do it a second time to test that no cookies are leaking from one call
324
    # to the other
325
    json_res = app.get('/stub-invoices/fake/httpcall').json
326
    assert json_res['cookie1'] is None
327
    assert json_res['cookie2'] == 'somecookie=somecookievalue'
tests/test_requests.py
6 6
from httmock import urlmatch, HTTMock, response
7 7

  
8 8
from django.test import override_settings
9
import requests
9 10

  
10 11
from passerelle.utils import Request, CaseInsensitiveDict
11 12
from passerelle.utils.http_authenticators import HawkAuth
......
327 328
        assert mocked_get.call_args[1]['timeout'] == 42
328 329
        Request(logger=logger).get('http://example.net/whatever', timeout=None)
329 330
        assert mocked_get.call_args[1]['timeout'] is None
331

  
332

  
333
def test_requests_cookies(caplog):
334
    resource = MockResource()
335
    resource.cookiejar = requests.cookies.cookiejar_from_dict({})
336
    logger = logging.getLogger('requests')
337
    request = Request(resource=resource, logger=logger)
338

  
339
    headers = {'Set-Cookie': 'somecookie=somecookievalue'}
340
    with utils.mock_url('http://some.example.org/', 'ok', headers):
341
        response = request.get('http://some.example.org/')
342
        assert response.cookies['somecookie'] == 'somecookievalue'
343
        # cookies are stored on the resource
344
        assert resource.cookiejar == response.cookies
345

  
346
    with utils.mock_url('http://some.example.org/', 'ok'):
347
        # cookies are sent back
348
        response = request.get('http://some.example.org/')
349
        assert response.request.headers['Cookie'] == 'somecookie=somecookievalue'
350

  
351
        # cookies sent back even with a new Request obj
352
        request = Request(resource=resource, logger=logger)
353
        response = request.get('http://some.example.org/')
354
        assert response.request.headers['Cookie'] == 'somecookie=somecookievalue'
tests/utils.py
30 30
        return json.loads(self.content)
31 31

  
32 32

  
33
def mock_url(url, response):
33
def mock_url(url, response, headers=None):
34 34
    parsed = urlparse.urlparse(url)
35 35
    if not isinstance(response ,str):
36 36
        response = json.dumps(response)
37 37

  
38 38
    @httmock.urlmatch(netloc=parsed.netloc, path=parsed.path)
39 39
    def mocked(url, request):
40
        return httmock.response(200, response, request=request)
40
        return httmock.response(200, response, request=request, headers=headers)
41 41
    return httmock.HTTMock(mocked)
42 42

  
43 43

  
44
-