|
| 1 | +""" |
| 2 | +This module standarize http traffic and the error handling for further communication with the GOG Galaxy 2.0. |
| 3 | +
|
| 4 | +It is recommended to use provided convenient methods for HTTP requests, especially when dealing with authorized sessions. |
| 5 | +Examplary simple web service could looks like: |
| 6 | +
|
| 7 | + .. code-block:: python |
| 8 | +
|
| 9 | + import logging |
| 10 | + from galaxy.http import create_client_session, handle_exception |
| 11 | +
|
| 12 | + class BackendClient: |
| 13 | + AUTH_URL = 'my-integration.com/auth' |
| 14 | + HEADERS = { |
| 15 | + "My-Custom-Header": "true", |
| 16 | + } |
| 17 | + def __init__(self): |
| 18 | + self._session = create_client_session(headers=self.HEADERS) |
| 19 | +
|
| 20 | + async def authenticate(self): |
| 21 | + await self._session.request('POST', self.AUTH_URL) |
| 22 | +
|
| 23 | + async def close(self): |
| 24 | + # to be called on plugin shutdown |
| 25 | + await self._session.close() |
| 26 | +
|
| 27 | + async def _authorized_request(self, method, url, *args, **kwargs): |
| 28 | + with handle_exceptions(): |
| 29 | + return await self._session.request(method, url, *args, **kwargs) |
| 30 | +""" |
| 31 | + |
1 | 32 | import asyncio
|
2 | 33 | import ssl
|
3 | 34 | from contextlib import contextmanager
|
|
13 | 44 | )
|
14 | 45 |
|
15 | 46 |
|
| 47 | +#: Default limit of the simultaneous connections for ssl connector. |
16 | 48 | DEFAULT_LIMIT = 20
|
17 |
| -DEFAULT_TIMEOUT = 60 # seconds |
| 49 | +#: Default timeout in seconds used for client session. |
| 50 | +DEFAULT_TIMEOUT = 60 |
18 | 51 |
|
19 | 52 |
|
20 | 53 | class HttpClient:
|
21 |
| - """Deprecated""" |
| 54 | + """ |
| 55 | + .. deprecated:: 0.41 |
| 56 | + Use http module functions instead |
| 57 | + """ |
22 | 58 | def __init__(self, limit=DEFAULT_LIMIT, timeout=aiohttp.ClientTimeout(total=DEFAULT_TIMEOUT), cookie_jar=None):
|
23 | 59 | connector = create_tcp_connector(limit=limit)
|
24 | 60 | self._session = create_client_session(connector=connector, timeout=timeout, cookie_jar=cookie_jar)
|
25 | 61 |
|
26 | 62 | async def close(self):
|
| 63 | + """Closes connection. Should be called in :meth:`~galaxy.api.plugin.Plugin.shutdown`""" |
27 | 64 | await self._session.close()
|
28 | 65 |
|
29 | 66 | async def request(self, method, url, *args, **kwargs):
|
30 | 67 | with handle_exception():
|
31 | 68 | return await self._session.request(method, url, *args, **kwargs)
|
32 | 69 |
|
33 | 70 |
|
34 |
| -def create_tcp_connector(*args, **kwargs): |
| 71 | +def create_tcp_connector(*args, **kwargs) -> aiohttp.TCPConnector: |
| 72 | + """ |
| 73 | + Creates TCP connector with resonable defaults. |
| 74 | + For details about available parameters refer to |
| 75 | + `aiohttp.TCPConnector <https://docs.aiohttp.org/en/stable/client_reference.html#tcpconnector>`_ |
| 76 | + """ |
35 | 77 | ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
36 | 78 | ssl_context.load_verify_locations(certifi.where())
|
37 | 79 | kwargs.setdefault("ssl", ssl_context)
|
38 | 80 | kwargs.setdefault("limit", DEFAULT_LIMIT)
|
39 |
| - return aiohttp.TCPConnector(*args, **kwargs) |
| 81 | + return aiohttp.TCPConnector(*args, **kwargs) # type: ignore due to https://github.com/python/mypy/issues/4001 |
| 82 | + |
| 83 | + |
| 84 | +def create_client_session(*args, **kwargs) -> aiohttp.ClientSession: |
| 85 | + """ |
| 86 | + Creates client session with resonable defaults. |
| 87 | + For details about available parameters refer to |
| 88 | + `aiohttp.ClientSession <https://docs.aiohttp.org/en/stable/client_reference.html>`_ |
40 | 89 |
|
| 90 | + Examplary customization: |
41 | 91 |
|
42 |
| -def create_client_session(*args, **kwargs): |
| 92 | + .. code-block:: python |
| 93 | +
|
| 94 | + from galaxy.http import create_client_session, create_tcp_connector |
| 95 | +
|
| 96 | + session = create_client_session( |
| 97 | + headers={ |
| 98 | + "Keep-Alive": "true" |
| 99 | + }, |
| 100 | + connector=create_tcp_connector(limit=40), |
| 101 | + timeout=100) |
| 102 | + """ |
43 | 103 | kwargs.setdefault("connector", create_tcp_connector())
|
44 | 104 | kwargs.setdefault("timeout", aiohttp.ClientTimeout(total=DEFAULT_TIMEOUT))
|
45 | 105 | kwargs.setdefault("raise_for_status", True)
|
46 |
| - return aiohttp.ClientSession(*args, **kwargs) |
| 106 | + return aiohttp.ClientSession(*args, **kwargs) # type: ignore due to https://github.com/python/mypy/issues/4001 |
47 | 107 |
|
48 | 108 |
|
49 | 109 | @contextmanager
|
50 | 110 | def handle_exception():
|
| 111 | + """ |
| 112 | + Context manager translating network related exceptions |
| 113 | + to custom :mod:`~galaxy.api.errors`. |
| 114 | + """ |
51 | 115 | try:
|
52 | 116 | yield
|
53 | 117 | except asyncio.TimeoutError:
|
@@ -78,4 +142,3 @@ def handle_exception():
|
78 | 142 | except aiohttp.ClientError:
|
79 | 143 | logging.exception("Caught exception while performing request")
|
80 | 144 | raise UnknownError()
|
81 |
| - |
|
0 commit comments