userver
C++ Async Framework
Toggle main menu visibility
Loading...
Searching...
No Matches
service_client.py
1
import
json
2
import
ssl
3
import
typing
4
import
uuid
5
6
import
aiohttp
7
import
yarl
8
9
from
testsuite
import
types
10
from
testsuite.utils
import
http, url_util
11
12
DEFAULT_HOST =
'localhost'
13
DEFAULT_TIMEOUT = 120.0
14
15
TResponse = typing.TypeVar(
16
'TResponse'
,
17
aiohttp.ClientResponse,
18
http.ClientResponse,
19
)
20
21
22
class
BaseAiohttpClient
:
23
def
__init__
(
24
self,
25
base_url: str,
26
*,
27
session: aiohttp.ClientSession,
28
ssl_context: ssl.SSLContext |
None
=
None
,
29
span_id_header: str |
None
=
None
,
30
headers: dict[str, str] |
None
=
None
,
31
timeout: float = DEFAULT_TIMEOUT,
32
):
33
"""
34
:param base_url: Base client url
35
:param session: ``aiohttp.ClientSession`` instance
36
:param headers: default request headers dictionary
37
:param timeout: http client default timeout
38
"""
39
self.
_base_url
= url_util.ensure_trailing_separator(base_url)
40
self.
_headers
= headers
or
{}
41
self.
_timeout
= timeout
42
self.
_session
= session
43
self.
_ssl_context
= ssl_context
44
self.
_span_id_header
= span_id_header
45
46
def
url(self, path: str | yarl.URL):
47
if
isinstance(path, str):
48
return
url_util.join(self.
_base_url
, path)
49
return
path
50
51
async def
_aiohttp_request(
52
self,
53
http_method: str,
54
path: str | yarl.URL,
55
headers: dict[str, str] |
None
=
None
,
56
bearer: str |
None
=
None
,
57
x_real_ip: str |
None
=
None
,
58
**kwargs,
59
) -> aiohttp.ClientResponse:
60
url = self.
url
(path)
61
headers = self.
_build_headers
(
62
headers,
63
bearer=bearer,
64
x_real_ip=x_real_ip,
65
)
66
kwargs[
'timeout'
] = kwargs.get(
'timeout'
, self.
_timeout
)
67
68
params = kwargs.get(
'params'
,
None
)
69
if
params
is
not
None
:
70
kwargs[
'params'
] = _flatten(params)
71
response = await self.
_session
.request(
72
http_method,
73
url,
74
headers=headers,
75
ssl=self.
_ssl_context
,
# type: ignore[arg-type]
76
**kwargs,
77
)
78
return
response
79
80
def
_build_headers(
81
self,
82
user_headers: dict[str, str] |
None
=
None
,
83
bearer: str |
None
=
None
,
84
x_real_ip: str |
None
=
None
,
85
) -> dict[str, str]:
86
headers = self.
_headers
.copy()
87
if
user_headers:
88
headers.update(user_headers)
89
if
bearer:
90
headers[
'Authorization'
] =
'Bearer %s'
% bearer
91
if
x_real_ip:
92
headers[
'X-Real-IP'
] = x_real_ip
93
if
self.
_span_id_header
and
self.
_span_id_header
not
in
headers:
94
headers[self.
_span_id_header
] = uuid.uuid4().hex
95
96
headers = {
97
key:
''
if
value
is
None
else
value
98
for
key, value
in
headers.items()
99
}
100
return
headers
101
102
103
class
GenericClient
(
BaseAiohttpClient
, typing.Generic[TResponse]):
104
"""Basic asyncio HTTP service client."""
105
106
async def
post
(
107
self,
108
path: str,
109
json: types.JsonAnyOptional =
None
,
110
data: typing.Any =
None
,
111
params: dict[str, str] |
None
=
None
,
112
bearer: str |
None
=
None
,
113
x_real_ip: str |
None
=
None
,
114
headers: dict[str, str] |
None
=
None
,
115
**kwargs,
116
) -> TResponse:
117
"""Perform HTTP POST request."""
118
return
await self.
_request
(
119
'POST'
,
120
path,
121
json=json,
122
data=data,
123
params=params,
124
headers=headers,
125
bearer=bearer,
126
x_real_ip=x_real_ip,
127
**kwargs,
128
)
129
130
async def
put
(
131
self,
132
path,
133
json: types.JsonAnyOptional =
None
,
134
data: typing.Any =
None
,
135
params: dict[str, str] |
None
=
None
,
136
bearer: str |
None
=
None
,
137
x_real_ip: str |
None
=
None
,
138
headers: dict[str, str] |
None
=
None
,
139
**kwargs,
140
) -> TResponse:
141
"""Perform HTTP PUT request."""
142
return
await self.
_request
(
143
'PUT'
,
144
path,
145
json=json,
146
data=data,
147
params=params,
148
headers=headers,
149
bearer=bearer,
150
x_real_ip=x_real_ip,
151
**kwargs,
152
)
153
154
async def
patch
(
155
self,
156
path,
157
json: types.JsonAnyOptional =
None
,
158
data: typing.Any =
None
,
159
params: dict[str, str] |
None
=
None
,
160
bearer: str |
None
=
None
,
161
x_real_ip: str |
None
=
None
,
162
headers: dict[str, str] |
None
=
None
,
163
**kwargs,
164
) -> TResponse:
165
"""Perform HTTP PATCH request."""
166
return
await self.
_request
(
167
'PATCH'
,
168
path,
169
json=json,
170
data=data,
171
params=params,
172
headers=headers,
173
bearer=bearer,
174
x_real_ip=x_real_ip,
175
**kwargs,
176
)
177
178
async def
get
(
179
self,
180
path: str,
181
headers: dict[str, str] |
None
=
None
,
182
bearer: str |
None
=
None
,
183
x_real_ip: str |
None
=
None
,
184
**kwargs,
185
) -> TResponse:
186
"""Perform HTTP GET request."""
187
return
await self.
_request
(
188
'GET'
,
189
path,
190
headers=headers,
191
bearer=bearer,
192
x_real_ip=x_real_ip,
193
**kwargs,
194
)
195
196
async def
delete
(
197
self,
198
path: str,
199
headers: dict[str, str] |
None
=
None
,
200
bearer: str |
None
=
None
,
201
x_real_ip: str |
None
=
None
,
202
**kwargs,
203
) -> TResponse:
204
"""Perform HTTP DELETE request."""
205
return
await self.
_request
(
206
'DELETE'
,
207
path,
208
headers=headers,
209
bearer=bearer,
210
x_real_ip=x_real_ip,
211
**kwargs,
212
)
213
214
async def
options
(
215
self,
216
path: str,
217
headers: dict[str, str] |
None
=
None
,
218
bearer: str |
None
=
None
,
219
x_real_ip: str |
None
=
None
,
220
**kwargs,
221
) -> TResponse:
222
"""Perform HTTP OPTIONS request."""
223
return
await self.
_request
(
224
'OPTIONS'
,
225
path,
226
headers=headers,
227
bearer=bearer,
228
x_real_ip=x_real_ip,
229
**kwargs,
230
)
231
232
async def
request
(
233
self,
234
http_method: str,
235
path: str,
236
**kwargs,
237
) -> TResponse:
238
"""Perform HTTP ``http_method`` request."""
239
return
await self.
_request
(http_method, path, **kwargs)
240
241
async def
_request(
242
self,
243
http_method: str,
244
path: str | yarl.URL,
245
headers: dict[str, str] |
None
=
None
,
246
bearer: str |
None
=
None
,
247
x_real_ip: str |
None
=
None
,
248
**kwargs,
249
) -> TResponse:
250
raise
NotImplementedError
251
252
253
class
AiohttpClient
(
GenericClient
[aiohttp.ClientResponse]):
254
async def
_request(
255
self,
256
http_method: str,
257
path: str | yarl.URL,
258
headers: dict[str, str] |
None
=
None
,
259
bearer: str |
None
=
None
,
260
x_real_ip: str |
None
=
None
,
261
**kwargs,
262
) -> aiohttp.ClientResponse:
263
return
await self.
_aiohttp_request
(
264
http_method,
265
path,
266
headers,
267
bearer,
268
x_real_ip,
269
**kwargs,
270
)
271
272
273
class
Client
(
GenericClient
[
http.ClientResponse
]):
274
async def
_request(
275
self,
276
http_method: str,
277
path: str | yarl.URL,
278
headers: dict[str, str] |
None
=
None
,
279
bearer: str |
None
=
None
,
280
x_real_ip: str |
None
=
None
,
281
**kwargs,
282
) ->
http.ClientResponse
:
283
response = await self.
_aiohttp_request
(
284
http_method,
285
path,
286
headers,
287
bearer,
288
x_real_ip,
289
**kwargs,
290
)
291
return
await self.
_wrap_client_response
(response)
292
293
def
_wrap_client_response(
294
self,
295
response,
296
) -> typing.Awaitable[http.ClientResponse]:
297
return
http.wrap_client_response(response, json_loads=json.loads)
298
299
300
def
_flatten(query_params):
301
result = []
302
iterable = (
303
query_params.items()
if
isinstance(query_params, dict)
else
query_params
304
)
305
for
key, value
in
iterable:
306
if
isinstance(value, (tuple, list)):
307
for
element
in
value:
308
result.append((key, str(element)))
309
else
:
310
result.append((key, str(value)))
311
return
result
en
testsuite
daemons
service_client.py
Generated on
for userver by
Doxygen
1.17.0