drb-driver-http 1.3.7__tar.gz → 1.3.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. {drb_driver_http-1.3.7/drb_driver_http.egg-info → drb_driver_http-1.3.8}/PKG-INFO +1 -1
  2. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/drb/drivers/http/_version.py +3 -3
  3. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/drb/drivers/http/http.py +14 -4
  4. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8/drb_driver_http.egg-info}/PKG-INFO +1 -1
  5. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/drb_driver_http.egg-info/SOURCES.txt +1 -0
  6. drb_driver_http-1.3.8/tests/test_drb_http_security.py +45 -0
  7. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/tests/test_drb_impl_http.py +2 -1
  8. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/LICENCE.txt +0 -0
  9. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/README.md +0 -0
  10. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/drb/drivers/http/__init__.py +0 -0
  11. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/drb/drivers/http/oauth2/HTTPOAuth2.py +0 -0
  12. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/drb/drivers/http/oauth2/__init__.py +0 -0
  13. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/drb/drivers/http/oauth2/oauth2.py +0 -0
  14. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/drb/exceptions/http.py +0 -0
  15. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/drb/topics/http/__init__.py +0 -0
  16. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/drb/topics/http/cortex.yml +0 -0
  17. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/drb_driver_http.egg-info/dependency_links.txt +0 -0
  18. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/drb_driver_http.egg-info/entry_points.txt +0 -0
  19. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/drb_driver_http.egg-info/not-zip-safe +0 -0
  20. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/drb_driver_http.egg-info/requires.txt +0 -0
  21. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/drb_driver_http.egg-info/top_level.txt +0 -0
  22. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/pyproject.toml +0 -0
  23. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/requirements.txt +0 -0
  24. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/setup.cfg +0 -0
  25. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/setup.py +0 -0
  26. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/tests/test_drb_http_basic_auth.py +0 -0
  27. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/tests/test_drb_http_bearer.py +0 -0
  28. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/tests/test_drb_http_factory.py +0 -0
  29. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/tests/test_drb_http_keyring.py +0 -0
  30. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/tests/test_drb_http_signature.py +0 -0
  31. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/tests/test_drb_https_signature.py +0 -0
  32. {drb_driver_http-1.3.7 → drb_driver_http-1.3.8}/versioneer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: drb-driver-http
3
- Version: 1.3.7
3
+ Version: 1.3.8
4
4
  Summary: DRB Http driver
5
5
  Author: GAEL Systems
6
6
  Author-email: drb-python@gael.fr
@@ -8,11 +8,11 @@ import json
8
8
 
9
9
  version_json = '''
10
10
  {
11
- "date": "2025-12-03T14:08:32+0100",
11
+ "date": "2026-06-10T18:50:43+0200",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "7f16365dce55500f72150e6270825fae5d0fbbc3",
15
- "version": "1.3.7"
14
+ "full-revisionid": "beaa911202e6cffa54953c69039b9cd65ce53d5c",
15
+ "version": "1.3.8"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
@@ -21,6 +21,12 @@ from tenacity import retry, stop_after_attempt, stop_after_delay, \
21
21
  from drb.exceptions.http import DrbHttpServerException, \
22
22
  DrbHttpNodeException, DrbHttpAuthException
23
23
 
24
+ # Default (connect, read) timeout in seconds for outbound HTTP requests.
25
+ # Without it a slow or malicious server blocks the calling thread forever.
26
+ # This driver is the OGC/odata trunk, so the timeout propagates to the
27
+ # wms/wcs/wmts/wxs/odata drivers built on top of it.
28
+ _HTTP_TIMEOUT = (10, 60)
29
+
24
30
 
25
31
  class EmptyAuth(AuthBase):
26
32
  """
@@ -40,7 +46,8 @@ class EmptyAuth(AuthBase):
40
46
  retry=retry_if_exception_type(DrbHttpNodeException))
41
47
  def get(path: str, auth: AuthBase, redirect, headers, params: Dict[str, Any]):
42
48
  return requests.get(path, stream=True, auth=auth, allow_redirects=redirect,
43
- headers=headers, params=params)
49
+ headers=headers, params=params,
50
+ timeout=_HTTP_TIMEOUT)
44
51
 
45
52
 
46
53
  @retry(stop=stop_after_attempt(5),
@@ -54,6 +61,7 @@ def head(path: str, auth: AuthBase, redirect, params: Dict[str, Any]):
54
61
  path,
55
62
  auth=auth,
56
63
  allow_redirects=redirect,
64
+ timeout=_HTTP_TIMEOUT,
57
65
  **params
58
66
  )
59
67
 
@@ -261,11 +269,12 @@ class DrbHttpNode(AbstractNode):
261
269
 
262
270
  def __init__(self, path, auth: AuthBase = None,
263
271
  redirect=True,
264
- params: Dict[str, Any] = {}):
272
+ params: Dict[str, Any] = None):
265
273
  super().__init__()
266
274
  self._path = path
267
275
  self._auth = auth
268
- self._params = params
276
+ # Avoid a shared mutable default (B006): a new dict per instance.
277
+ self._params = params if params is not None else {}
269
278
  self._children = []
270
279
  self._redirect = redirect
271
280
  self.add_impl(io.BytesIO, _to_stream)
@@ -389,7 +398,8 @@ class DrbHttpNode(AbstractNode):
389
398
  headers=headers,
390
399
  json=data,
391
400
  allow_redirects=redirect,
392
- auth=auth)
401
+ auth=auth,
402
+ timeout=_HTTP_TIMEOUT)
393
403
  return DrbHttpResponse(path=url, response=response)
394
404
 
395
405
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: drb-driver-http
3
- Version: 1.3.7
3
+ Version: 1.3.8
4
4
  Summary: DRB Http driver
5
5
  Author: GAEL Systems
6
6
  Author-email: drb-python@gael.fr
@@ -25,6 +25,7 @@ tests/test_drb_http_basic_auth.py
25
25
  tests/test_drb_http_bearer.py
26
26
  tests/test_drb_http_factory.py
27
27
  tests/test_drb_http_keyring.py
28
+ tests/test_drb_http_security.py
28
29
  tests/test_drb_http_signature.py
29
30
  tests/test_drb_https_signature.py
30
31
  tests/test_drb_impl_http.py
@@ -0,0 +1,45 @@
1
+ import unittest
2
+ from unittest.mock import patch, MagicMock
3
+
4
+ from drb.drivers.http import DrbHttpNode
5
+ from drb.drivers.http.http import get, head, EmptyAuth, _HTTP_TIMEOUT
6
+
7
+
8
+ class TestHttpTimeout(unittest.TestCase):
9
+ """Every outbound request must carry an explicit timeout (SEC-001)."""
10
+
11
+ @patch('drb.drivers.http.http.requests')
12
+ def test_get_passes_timeout(self, mock_requests):
13
+ get('http://example.org', EmptyAuth(), True, None, {})
14
+ self.assertEqual(_HTTP_TIMEOUT,
15
+ mock_requests.get.call_args.kwargs['timeout'])
16
+
17
+ @patch('drb.drivers.http.http.requests')
18
+ def test_head_passes_timeout(self, mock_requests):
19
+ head('http://example.org', EmptyAuth(), True, {})
20
+ self.assertEqual(_HTTP_TIMEOUT,
21
+ mock_requests.head.call_args.kwargs['timeout'])
22
+
23
+ @patch('drb.drivers.http.http.requests')
24
+ def test_post_passes_timeout(self, mock_requests):
25
+ resp = MagicMock()
26
+ resp.headers.items.return_value = []
27
+ resp.content = b''
28
+ mock_requests.post.return_value = resp
29
+ DrbHttpNode.post('http://example.org', data={})
30
+ self.assertEqual(_HTTP_TIMEOUT,
31
+ mock_requests.post.call_args.kwargs['timeout'])
32
+
33
+
34
+ class TestHttpParamsDefault(unittest.TestCase):
35
+ """params must not be a shared mutable default (B006)."""
36
+
37
+ def test_params_not_shared_between_instances(self):
38
+ n1 = DrbHttpNode('http://a')
39
+ n2 = DrbHttpNode('http://b')
40
+ n1.params['k'] = 'v'
41
+ self.assertEqual({}, n2.params)
42
+
43
+
44
+ if __name__ == '__main__':
45
+ unittest.main()
@@ -218,4 +218,5 @@ class TestDrbHttp(unittest.TestCase):
218
218
  headers={'Content-Type': 'application/json'},
219
219
  json='{"test1": "value1", "test2": "value2"}',
220
220
  allow_redirects=True,
221
- auth=None)
221
+ auth=None,
222
+ timeout=(10, 60))