1
- # TODO __all__ = []
1
+ __all__ = [
2
+ "HTTPClient" ,
3
+ "AioHTTPClient" ,
4
+ "DefaultHTTPClient" ,
5
+ ]
2
6
3
7
from abc import ABC , abstractmethod
4
- from typing import Optional
8
+ from typing import Any , Optional
5
9
6
- from aiohttp import BaseConnector , BasicAuth , ClientSession , ClientTimeout
10
+ from aiohttp import BaseConnector , BasicAuth , ClientSession , ClientTimeout , TcpConnector
7
11
from request import Request
8
12
from response import Response
9
13
10
14
11
- class Session (ABC ): # pragma: no cover
12
- """Abstract base class for HTTP sessions."""
13
-
14
- @abstractmethod
15
- async def request (self , request : Request ) -> Response :
16
- """Send an HTTP request.
17
-
18
- This method must be overridden by the user.
19
-
20
- :param request: HTTP request.
21
- :type request: arangoasync.request.Request
22
- :returns: HTTP response.
23
- :rtype: arangoasync.response.Response
24
- """
25
- raise NotImplementedError
26
-
27
- @abstractmethod
28
- async def close (self ) -> None :
29
- """Close the session.
30
-
31
- This method must be overridden by the user.
32
- """
33
- raise NotImplementedError
34
-
35
-
36
15
class HTTPClient (ABC ): # pragma: no cover
37
- """Abstract base class for HTTP clients."""
16
+ """Abstract base class for HTTP clients.
17
+ Custom HTTP clients should inherit from this class.
18
+ """
38
19
39
20
@abstractmethod
40
- def create_session (self , host : str ) -> Session :
41
- """Return a new requests session given the host URL.
21
+ def create_session (self , host : str ) -> Any :
22
+ """Return a new session given the base host URL.
42
23
43
24
This method must be overridden by the user.
44
25
45
26
:param host: ArangoDB host URL.
46
27
:type host: str
47
28
:returns: Requests session object.
48
- :rtype: arangoasync.http.Session
29
+ :rtype: Any
49
30
"""
50
31
raise NotImplementedError
51
32
52
33
@abstractmethod
53
34
async def send_request (
54
35
self ,
55
- session : Session ,
56
- url : str ,
36
+ session : Any ,
57
37
request : Request ,
58
38
) -> Response :
59
39
"""Send an HTTP request.
60
40
61
41
This method must be overridden by the user.
62
42
63
43
:param session: Session object.
64
- :type session: arangoasync.http.Session
65
- :param url: Request URL.
66
- :type url: str
44
+ :type session: Any
67
45
:param request: HTTP request.
68
46
:type request: arangoasync.request.Request
69
47
:returns: HTTP response.
70
- :rtype: arango .response.Response
48
+ :rtype: arangoasync .response.Response
71
49
"""
72
50
raise NotImplementedError
73
51
74
52
75
- class DefaultSession (Session ):
76
- """Wrapper on top of an aiohttp.ClientSession."""
53
+ class AioHTTPClient (HTTPClient ):
54
+ """HTTP client implemented on top of [aiohttp](https://docs.aiohttp.org/en/stable/).
55
+
56
+ :param connector: Supports connection pooling.
57
+ By default, 100 simultaneous connections are supported, with a 60-second timeout
58
+ for connection reusing after release.
59
+ :type connector: aiohttp.BaseConnector | None
60
+ :param timeout: Timeout settings.
61
+ 300s total timeout by default for a complete request/response operation.
62
+ :type timeout: aiohttp.ClientTimeout | None
63
+ :param read_bufsize: Size of read buffer (64KB default).
64
+ :type read_bufsize: int
65
+ :param auth: HTTP authentication helper.
66
+ Should be used for specifying authorization data in client API.
67
+ :type auth: aiohttp.BasicAuth | None
68
+ :param compression_threshold: Will compress requests to the server if
69
+ the size of the request body (in bytes) is at least the value of this
70
+ option.
71
+ :type compression_threshold: int
72
+ """
77
73
78
74
def __init__ (
79
75
self ,
80
- host : str ,
81
- connector : BaseConnector ,
82
- timeout : ClientTimeout ,
76
+ connector : Optional [BaseConnector ] = None ,
77
+ timeout : Optional [ClientTimeout ] = None ,
83
78
read_bufsize : int = 2 ** 16 ,
84
79
auth : Optional [BasicAuth ] = None ,
80
+ compression_threshold : int = 1024 ,
85
81
) -> None :
86
- """Initialize the session.
82
+ self ._connector = connector or TcpConnector (
83
+ keepalive_timeout = 60 , # timeout for connection reusing after releasing
84
+ limit = 100 , # total number simultaneous connections
85
+ )
86
+ self ._timeout = timeout or ClientTimeout (
87
+ total = 300 , # total number of seconds for the whole request
88
+ connect = 60 , # max number of seconds for acquiring a pool connection
89
+ )
90
+ self ._read_bufsize = read_bufsize
91
+ self ._auth = auth
92
+ self ._compression_threshold = compression_threshold
87
93
88
- :param host: ArangoDB coordinator URL (eg http://localhost:8530).
94
+ def create_session (self , host : str ) -> ClientSession :
95
+ """Return a new session given the base host URL.
96
+
97
+ :param host: ArangoDB host URL. Typically the address and port of a coordinator,
98
+ for example "http://127.0.0.1:8529".
89
99
:type host: str
90
- :param connector: Supports connection pooling.
91
- :type connector: aiohttp.BaseConnector
92
- :param timeout: Request timeout settings.
93
- :type timeout: aiohttp.ClientTimeout
94
- :param read_bufsize: Size of read buffer. 64 Kib by default.
95
- :type read_bufsize: int
96
- :param auth: HTTP Authorization.
97
- :type auth: aiohttp.BasicAuth | None
100
+ :returns: Session object.
101
+ :rtype: aiohttp.ClientSession
98
102
"""
99
- self ._session = ClientSession (
100
- base_url = host ,
101
- connector = connector ,
102
- timeout = timeout ,
103
- auth = auth ,
104
- read_bufsize = read_bufsize ,
105
- connector_owner = False ,
106
- auto_decompress = True ,
103
+ return ClientSession (
104
+ connector = self ._connector ,
105
+ timeout = self ._timeout ,
106
+ auth = self ._auth ,
107
+ read_bufsize = self ._read_bufsize ,
107
108
)
108
109
109
- async def request (self , request : Request ) -> Response :
110
+ async def send_request (
111
+ self ,
112
+ session : ClientSession ,
113
+ request : Request ,
114
+ ) -> Response :
110
115
"""Send an HTTP request.
111
116
117
+ :param session: Session object.
118
+ :type session: aiohttp.ClientSession
112
119
:param request: HTTP request.
113
120
:type request: arangoasync.request.Request
114
121
:returns: HTTP response.
@@ -119,13 +126,15 @@ async def request(self, request: Request) -> Response:
119
126
headers = request .headers
120
127
params = request .params
121
128
data = request .data
129
+ compress = len (data ) >= self ._compression_threshold
122
130
123
- async with self . _session .request (
131
+ async with session .request (
124
132
method .name ,
125
133
endpoint ,
126
134
headers = headers ,
127
135
params = params ,
128
136
data = data ,
137
+ compress = compress ,
129
138
) as response :
130
139
raw_body = await response .read ()
131
140
return Response (
@@ -137,9 +146,5 @@ async def request(self, request: Request) -> Response:
137
146
raw_body = raw_body ,
138
147
)
139
148
140
- async def close (self ) -> None :
141
- """Close the session."""
142
- await self ._session .close ()
143
-
144
149
145
- # TODO implement DefaultHTTPClient
150
+ DefaultHTTPClient = AioHTTPClient
0 commit comments