huace-aigc-auth-client 1.1.31__tar.gz → 1.1.33__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 (21) hide show
  1. {huace_aigc_auth_client-1.1.31/huace_aigc_auth_client.egg-info → huace_aigc_auth_client-1.1.33}/PKG-INFO +1 -1
  2. {huace_aigc_auth_client-1.1.31 → huace_aigc_auth_client-1.1.33}/huace_aigc_auth_client/__init__.py +3 -1
  3. huace_aigc_auth_client-1.1.33/huace_aigc_auth_client/auth_request.py +691 -0
  4. {huace_aigc_auth_client-1.1.31 → huace_aigc_auth_client-1.1.33/huace_aigc_auth_client.egg-info}/PKG-INFO +1 -1
  5. {huace_aigc_auth_client-1.1.31 → huace_aigc_auth_client-1.1.33}/pyproject.toml +1 -1
  6. huace_aigc_auth_client-1.1.31/huace_aigc_auth_client/auth_request.py +0 -324
  7. {huace_aigc_auth_client-1.1.31 → huace_aigc_auth_client-1.1.33}/LICENSE +0 -0
  8. {huace_aigc_auth_client-1.1.31 → huace_aigc_auth_client-1.1.33}/MANIFEST.in +0 -0
  9. {huace_aigc_auth_client-1.1.31 → huace_aigc_auth_client-1.1.33}/QUICK_START.txt +0 -0
  10. {huace_aigc_auth_client-1.1.31 → huace_aigc_auth_client-1.1.33}/README.md +0 -0
  11. {huace_aigc_auth_client-1.1.31 → huace_aigc_auth_client-1.1.33}/huace_aigc_auth_client/api_stats_collector.py +0 -0
  12. {huace_aigc_auth_client-1.1.31 → huace_aigc_auth_client-1.1.33}/huace_aigc_auth_client/legacy_adapter.py +0 -0
  13. {huace_aigc_auth_client-1.1.31 → huace_aigc_auth_client-1.1.33}/huace_aigc_auth_client/sdk.py +0 -0
  14. {huace_aigc_auth_client-1.1.31 → huace_aigc_auth_client-1.1.33}/huace_aigc_auth_client/user_context.py +0 -0
  15. {huace_aigc_auth_client-1.1.31 → huace_aigc_auth_client-1.1.33}/huace_aigc_auth_client/webhook.py +0 -0
  16. {huace_aigc_auth_client-1.1.31 → huace_aigc_auth_client-1.1.33}/huace_aigc_auth_client/webhook_flask.py +0 -0
  17. {huace_aigc_auth_client-1.1.31 → huace_aigc_auth_client-1.1.33}/huace_aigc_auth_client.egg-info/SOURCES.txt +0 -0
  18. {huace_aigc_auth_client-1.1.31 → huace_aigc_auth_client-1.1.33}/huace_aigc_auth_client.egg-info/dependency_links.txt +0 -0
  19. {huace_aigc_auth_client-1.1.31 → huace_aigc_auth_client-1.1.33}/huace_aigc_auth_client.egg-info/requires.txt +0 -0
  20. {huace_aigc_auth_client-1.1.31 → huace_aigc_auth_client-1.1.33}/huace_aigc_auth_client.egg-info/top_level.txt +0 -0
  21. {huace_aigc_auth_client-1.1.31 → huace_aigc_auth_client-1.1.33}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: huace-aigc-auth-client
3
- Version: 1.1.31
3
+ Version: 1.1.33
4
4
  Summary: 华策AIGC Auth Client - 提供 Token 验证、用户信息获取、权限检查、旧系统接入等功能
5
5
  Author-email: Huace <support@huace.com>
6
6
  License: MIT
@@ -67,6 +67,7 @@ from .api_stats_collector import (
67
67
 
68
68
  from .auth_request import (
69
69
  auth_request,
70
+ async_auth_httpx_request
70
71
  )
71
72
 
72
73
  from .legacy_adapter import (
@@ -214,5 +215,6 @@ __all__ = [
214
215
  "stop_api_stats_collector",
215
216
  # 认证请求封装
216
217
  "auth_request",
218
+ "async_auth_httpx_request",
217
219
  ]
218
- __version__ = "1.1.31"
220
+ __version__ = "1.1.33"
@@ -0,0 +1,691 @@
1
+ """
2
+ 认证请求封装模块
3
+ 提供对 requests.request 和 httpx 的封装,自动添加认证信息和统计上报
4
+ """
5
+ import time
6
+ import logging
7
+ from typing import Optional, Dict, Any, Union
8
+ import requests
9
+ from requests import Response
10
+
11
+ try:
12
+ import httpx
13
+ HTTPX_AVAILABLE = True
14
+ except ImportError:
15
+ HTTPX_AVAILABLE = False
16
+ httpx = None
17
+
18
+ from .user_context import get_request_context
19
+ from .api_stats_collector import get_api_stats_collector
20
+
21
+ logger = logging.getLogger(__name__)
22
+ def setLogger(log):
23
+ """
24
+ 统一设置所有模块的 logger
25
+
26
+ Args:
27
+ log: logging.Logger 实例
28
+ """
29
+ global logger
30
+ logger = log
31
+
32
+ def auth_request(
33
+ method: str,
34
+ url: str,
35
+ params: Optional[Dict[str, Any]] = None,
36
+ data: Optional[Union[Dict[str, Any], str, bytes]] = None,
37
+ json: Optional[Dict[str, Any]] = None,
38
+ headers: Optional[Dict[str, str]] = None,
39
+ cookies: Optional[Dict[str, str]] = None,
40
+ files: Optional[Dict[str, Any]] = None,
41
+ auth: Optional[tuple] = None,
42
+ timeout: Optional[Union[float, tuple]] = None,
43
+ allow_redirects: bool = True,
44
+ proxies: Optional[Dict[str, str]] = None,
45
+ verify: Optional[Union[bool, str]] = None,
46
+ stream: bool = False,
47
+ cert: Optional[Union[str, tuple]] = None,
48
+ **kwargs
49
+ ) -> Response:
50
+ """
51
+ 认证请求封装函数
52
+
53
+ 基本参数与 requests.request 一致,会自动从 request_context 中获取认证信息并添加到请求头
54
+
55
+ Args:
56
+ method: HTTP 方法 (GET, POST, PUT, DELETE 等)
57
+ url: 请求 URL
58
+ params: URL 查询参数
59
+ data: 请求体数据 (form-data 或 raw)
60
+ json: JSON 请求体数据
61
+ headers: 请求头(会自动添加认证相关的头)
62
+ cookies: Cookies
63
+ files: 文件上传
64
+ auth: HTTP 认证元组
65
+ timeout: 超时时间(秒)
66
+ allow_redirects: 是否允许重定向
67
+ proxies: 代理配置
68
+ verify: SSL 证书验证
69
+ stream: 是否流式响应
70
+ cert: 客户端证书
71
+ **kwargs: 其他 requests.request 支持的参数
72
+
73
+ Returns:
74
+ Response: 响应对象
75
+
76
+ 自动添加的请求头(如果在 request_context 中存在):
77
+ - X-App-ID: 应用ID
78
+ - X-App-Secret: 应用密钥
79
+ - Authorization: Bearer token
80
+ - x-real-ip: 客户端真实IP
81
+ - user-agent: User Agent
82
+ - X-Trace-ID: 追踪ID
83
+ """
84
+ # 初始化 headers
85
+ if headers is None:
86
+ headers = {}
87
+ else:
88
+ headers = headers.copy() # 避免修改原始 headers
89
+
90
+ # 从 request_context 获取认证信息
91
+ request_context = get_request_context()
92
+
93
+ if request_context:
94
+ # 添加应用ID
95
+ app_id = request_context.get('app_id')
96
+ if app_id is not None:
97
+ headers['X-App-ID'] = str(app_id)
98
+
99
+ # 添加应用密钥
100
+ app_secret = request_context.get('app_secret')
101
+ if app_secret:
102
+ headers['X-App-Secret'] = app_secret
103
+
104
+ # 添加认证令牌
105
+ token = request_context.get('token')
106
+ if token:
107
+ headers['Authorization'] = f'Bearer {token}'
108
+
109
+ # 添加客户端IP
110
+ ip_address = request_context.get('ip_address')
111
+ if ip_address:
112
+ headers['x-real-ip'] = ip_address
113
+
114
+ # 添加 User Agent
115
+ user_agent = request_context.get('user_agent')
116
+ if user_agent:
117
+ headers['user-agent'] = user_agent
118
+
119
+ # 添加追踪ID
120
+ trace_id = request_context.get('trace_id')
121
+ if trace_id:
122
+ headers['X-Trace-ID'] = trace_id
123
+
124
+ # 记录开始时间
125
+ start_time = time.time()
126
+ response = None
127
+ error_message = None
128
+
129
+ try:
130
+ # 执行请求
131
+ logger.info(f"发起认证请求: {method} {url} with headers={headers} params={params} json={json} data={data}")
132
+ response = requests.request(
133
+ method=method,
134
+ url=url,
135
+ params=params,
136
+ data=data,
137
+ json=json,
138
+ headers=headers,
139
+ cookies=cookies,
140
+ files=files,
141
+ auth=auth,
142
+ timeout=timeout,
143
+ allow_redirects=allow_redirects,
144
+ proxies=proxies,
145
+ verify=verify,
146
+ stream=stream,
147
+ cert=cert,
148
+ **kwargs
149
+ )
150
+ logger.info(f"认证请求响应: {method} {url} 状态码: {response.status_code}")
151
+ return response
152
+
153
+ except Exception as e:
154
+ error_message = str(e)
155
+ logger.error(f"认证请求失败: {method} {url} 错误: {error_message}")
156
+ raise
157
+
158
+ finally:
159
+ # 计算响应时间
160
+ response_time = time.time() - start_time
161
+
162
+ # 上报统计信息
163
+ _report_stats(
164
+ url=url,
165
+ method=method,
166
+ response=response,
167
+ response_time=response_time,
168
+ error_message=error_message,
169
+ request_context=request_context,
170
+ headers=headers,
171
+ params=params,
172
+ json_data=json,
173
+ form_data=data
174
+ )
175
+
176
+
177
+ def _report_stats(
178
+ url: str,
179
+ method: str,
180
+ response: Optional[Response],
181
+ response_time: float,
182
+ error_message: Optional[str],
183
+ request_context: Optional[Dict[str, Any]],
184
+ headers: Optional[Dict[str, str]],
185
+ params: Optional[Dict[str, Any]],
186
+ json_data: Optional[Dict[str, Any]],
187
+ form_data: Optional[Union[Dict[str, Any], str, bytes]]
188
+ ):
189
+ """
190
+ 上报统计信息到远程服务
191
+
192
+ Args:
193
+ url: 请求 URL
194
+ method: HTTP 方法
195
+ response: 响应对象
196
+ response_time: 响应时间
197
+ error_message: 错误信息
198
+ request_context: 请求上下文
199
+ params: 查询参数
200
+ json_data: JSON 数据
201
+ form_data: 表单数据
202
+ """
203
+ try:
204
+ # 获取统计收集器
205
+ collector = get_api_stats_collector()
206
+ if not collector:
207
+ return
208
+
209
+ # 获取 token
210
+ token = request_context.get('token') if request_context else None
211
+ if not token:
212
+ return
213
+
214
+ # 解析 URL 获取路径
215
+ from urllib.parse import urlparse
216
+ parsed_url = urlparse(url)
217
+ api_path = parsed_url.path or '/'
218
+ # 带上协议和域名
219
+ api_path = f"{parsed_url.scheme}://{parsed_url.netloc}{parsed_url.path or '/'}"
220
+
221
+ # 获取状态码
222
+ status_code = response.status_code if response else 500
223
+
224
+ # 构建请求参数(与 api_stats_collector 格式一致)
225
+ request_params = {
226
+ 'query_params': params or {},
227
+ 'headers': headers
228
+ }
229
+
230
+ # 添加请求体数据
231
+ if json_data:
232
+ request_params['request_body'] = json_data
233
+ elif isinstance(form_data, dict):
234
+ request_params['form_params'] = form_data
235
+
236
+ # 收集统计
237
+ collector.collect(
238
+ api_path=api_path,
239
+ api_method=method.upper(),
240
+ status_code=status_code,
241
+ response_time=response_time,
242
+ token=token,
243
+ error_message=error_message,
244
+ request_params=request_params
245
+ )
246
+
247
+ except Exception as e:
248
+ # 静默失败,不影响主流程
249
+ logger.debug(f"统计上报失败: {e}")
250
+
251
+
252
+ # ============ HTTPX 异步请求封装 ============
253
+
254
+ if HTTPX_AVAILABLE:
255
+
256
+ async def async_auth_httpx_request(
257
+ method: str,
258
+ url: str,
259
+ params: Optional[Dict[str, Any]] = None,
260
+ data: Optional[Union[Dict[str, Any], str, bytes]] = None,
261
+ json: Optional[Dict[str, Any]] = None,
262
+ headers: Optional[Dict[str, str]] = None,
263
+ cookies: Optional[Dict[str, str]] = None,
264
+ files: Optional[Dict[str, Any]] = None,
265
+ auth: Optional[tuple] = None,
266
+ timeout: Optional[Union[float, httpx.Timeout]] = None,
267
+ follow_redirects: bool = True,
268
+ **kwargs
269
+ ) -> httpx.Response:
270
+ """
271
+ 异步认证请求封装函数(httpx)
272
+
273
+ 基本参数与 httpx.request 一致,会自动从 request_context 中获取认证信息并添加到请求头
274
+
275
+ Args:
276
+ method: HTTP 方法 (GET, POST, PUT, DELETE 等)
277
+ url: 请求 URL
278
+ params: URL 查询参数
279
+ data: 请求体数据 (form-data 或 raw)
280
+ json: JSON 请求体数据
281
+ headers: 请求头(会自动添加认证相关的头)
282
+ cookies: Cookies
283
+ files: 文件上传
284
+ auth: HTTP 认证元组
285
+ timeout: 超时时间(秒)
286
+ follow_redirects: 是否允许重定向
287
+ **kwargs: 其他 httpx.request 支持的参数
288
+
289
+ Returns:
290
+ httpx.Response: 响应对象
291
+
292
+ 自动添加的请求头(如果在 request_context 中存在):
293
+ - X-App-ID: 应用ID
294
+ - X-App-Secret: 应用密钥
295
+ - Authorization: Bearer token
296
+ - x-real-ip: 客户端真实IP
297
+ - user-agent: User Agent
298
+ - X-Trace-ID: 追踪ID
299
+ """
300
+ # 初始化 headers
301
+ if headers is None:
302
+ headers = {}
303
+ else:
304
+ headers = headers.copy() # 避免修改原始 headers
305
+
306
+ # 从 request_context 获取认证信息
307
+ request_context = get_request_context()
308
+
309
+ if request_context:
310
+ # 添加应用ID
311
+ app_id = request_context.get('app_id')
312
+ if app_id is not None:
313
+ headers['X-App-ID'] = str(app_id)
314
+
315
+ # 添加应用密钥
316
+ app_secret = request_context.get('app_secret')
317
+ if app_secret:
318
+ headers['X-App-Secret'] = app_secret
319
+
320
+ # 添加认证令牌
321
+ token = request_context.get('token')
322
+ if token:
323
+ headers['Authorization'] = f'Bearer {token}'
324
+
325
+ # 添加客户端IP
326
+ ip_address = request_context.get('ip_address')
327
+ if ip_address:
328
+ headers['x-real-ip'] = ip_address
329
+
330
+ # 添加 User Agent
331
+ user_agent = request_context.get('user_agent')
332
+ if user_agent:
333
+ headers['user-agent'] = user_agent
334
+
335
+ # 添加追踪ID
336
+ trace_id = request_context.get('trace_id')
337
+ if trace_id:
338
+ headers['X-Trace-ID'] = trace_id
339
+
340
+ # 记录开始时间
341
+ start_time = time.time()
342
+ response = None
343
+ error_message = None
344
+
345
+ try:
346
+ # 执行异步请求
347
+ logger.info(f"发起异步认证请求: {method} {url} with headers={headers} params={params} json={json} data={data}")
348
+
349
+ async with httpx.AsyncClient(timeout=timeout) as client:
350
+ response = await client.request(
351
+ method=method,
352
+ url=url,
353
+ params=params,
354
+ data=data,
355
+ json=json,
356
+ headers=headers,
357
+ cookies=cookies,
358
+ files=files,
359
+ auth=auth,
360
+ follow_redirects=follow_redirects,
361
+ **kwargs
362
+ )
363
+
364
+ logger.info(f"异步认证请求响应: {method} {url} 状态码: {response.status_code}")
365
+ return response
366
+
367
+ except Exception as e:
368
+ error_message = str(e)
369
+ logger.error(f"异步认证请求失败: {method} {url} 错误: {error_message}")
370
+ raise
371
+
372
+ finally:
373
+ # 计算响应时间
374
+ response_time = time.time() - start_time
375
+
376
+ # 上报统计信息
377
+ _report_stats(
378
+ url=url,
379
+ method=method,
380
+ response=response,
381
+ response_time=response_time,
382
+ error_message=error_message,
383
+ request_context=request_context,
384
+ headers=headers,
385
+ params=params,
386
+ json_data=json,
387
+ form_data=data
388
+ )
389
+
390
+
391
+ class AsyncAuthClient:
392
+ """
393
+ 异步认证客户端(httpx.AsyncClient 包装)
394
+
395
+ 提供可复用的异步 HTTP 客户端,自动处理认证信息和统计上报
396
+ """
397
+
398
+ def __init__(
399
+ self,
400
+ base_url: Optional[str] = None,
401
+ timeout: Optional[Union[float, httpx.Timeout]] = None,
402
+ follow_redirects: bool = True,
403
+ **kwargs
404
+ ):
405
+ """
406
+ 初始化异步认证客户端
407
+
408
+ Args:
409
+ base_url: 基础 URL
410
+ timeout: 超时配置
411
+ follow_redirects: 是否允许重定向
412
+ **kwargs: 其他 httpx.AsyncClient 支持的参数
413
+ """
414
+ self.base_url = base_url
415
+ self.timeout = timeout
416
+ self.follow_redirects = follow_redirects
417
+ self.client_kwargs = kwargs
418
+ self._client: Optional[httpx.AsyncClient] = None
419
+
420
+ async def __aenter__(self):
421
+ """进入异步上下文"""
422
+ self._client = httpx.AsyncClient(
423
+ base_url=self.base_url,
424
+ timeout=self.timeout,
425
+ follow_redirects=self.follow_redirects,
426
+ **self.client_kwargs
427
+ )
428
+ return self
429
+
430
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
431
+ """退出异步上下文"""
432
+ if self._client:
433
+ await self._client.aclose()
434
+ self._client = None
435
+
436
+ def _prepare_headers(self, headers: Optional[Dict[str, str]] = None) -> Dict[str, str]:
437
+ """准备请求头(添加认证信息)"""
438
+ # 初始化 headers
439
+ if headers is None:
440
+ headers = {}
441
+ else:
442
+ headers = headers.copy()
443
+
444
+ # 从 request_context 获取认证信息
445
+ request_context = get_request_context()
446
+
447
+ if request_context:
448
+ # 添加应用ID
449
+ app_id = request_context.get('app_id')
450
+ if app_id is not None:
451
+ headers['X-App-ID'] = str(app_id)
452
+
453
+ # 添加应用密钥
454
+ app_secret = request_context.get('app_secret')
455
+ if app_secret:
456
+ headers['X-App-Secret'] = app_secret
457
+
458
+ # 添加认证令牌
459
+ token = request_context.get('token')
460
+ if token:
461
+ headers['Authorization'] = f'Bearer {token}'
462
+
463
+ # 添加客户端IP
464
+ ip_address = request_context.get('ip_address')
465
+ if ip_address:
466
+ headers['x-real-ip'] = ip_address
467
+
468
+ # 添加 User Agent
469
+ user_agent = request_context.get('user_agent')
470
+ if user_agent:
471
+ headers['user-agent'] = user_agent
472
+
473
+ # 添加追踪ID
474
+ trace_id = request_context.get('trace_id')
475
+ if trace_id:
476
+ headers['X-Trace-ID'] = trace_id
477
+
478
+ return headers
479
+
480
+ async def _request(
481
+ self,
482
+ method: str,
483
+ url: str,
484
+ **kwargs
485
+ ) -> httpx.Response:
486
+ """执行请求(内部方法)"""
487
+ if self._client is None:
488
+ raise RuntimeError("Client not initialized. Use 'async with AsyncAuthClient()' context manager.")
489
+
490
+ # 准备 headers
491
+ headers = kwargs.pop('headers', None)
492
+ headers = self._prepare_headers(headers)
493
+
494
+ # 提取参数用于统计
495
+ params = kwargs.get('params')
496
+ json_data = kwargs.get('json')
497
+ form_data = kwargs.get('data')
498
+
499
+ # 记录开始时间
500
+ start_time = time.time()
501
+ response = None
502
+ error_message = None
503
+ request_context = get_request_context()
504
+
505
+ try:
506
+ # 执行请求
507
+ logger.info(f"AsyncAuthClient 发起请求: {method} {url} with headers={headers}")
508
+ response = await self._client.request(
509
+ method=method,
510
+ url=url,
511
+ headers=headers,
512
+ **kwargs
513
+ )
514
+ logger.info(f"AsyncAuthClient 请求响应: {method} {url} 状态码: {response.status_code}")
515
+ return response
516
+
517
+ except Exception as e:
518
+ error_message = str(e)
519
+ logger.error(f"AsyncAuthClient 请求失败: {method} {url} 错误: {error_message}")
520
+ raise
521
+
522
+ finally:
523
+ # 计算响应时间
524
+ response_time = time.time() - start_time
525
+
526
+ # 上报统计信息
527
+ full_url = str(self._client.build_request(method, url).url) if self._client else url
528
+ _report_stats(
529
+ url=full_url,
530
+ method=method,
531
+ response=response,
532
+ response_time=response_time,
533
+ error_message=error_message,
534
+ request_context=request_context,
535
+ headers=headers,
536
+ params=params,
537
+ json_data=json_data,
538
+ form_data=form_data
539
+ )
540
+
541
+ async def get(self, url: str, **kwargs) -> httpx.Response:
542
+ """GET 请求"""
543
+ return await self._request('GET', url, **kwargs)
544
+
545
+ async def post(self, url: str, **kwargs) -> httpx.Response:
546
+ """POST 请求"""
547
+ return await self._request('POST', url, **kwargs)
548
+
549
+ async def put(self, url: str, **kwargs) -> httpx.Response:
550
+ """PUT 请求"""
551
+ return await self._request('PUT', url, **kwargs)
552
+
553
+ async def delete(self, url: str, **kwargs) -> httpx.Response:
554
+ """DELETE 请求"""
555
+ return await self._request('DELETE', url, **kwargs)
556
+
557
+ async def patch(self, url: str, **kwargs) -> httpx.Response:
558
+ """PATCH 请求"""
559
+ return await self._request('PATCH', url, **kwargs)
560
+
561
+ async def head(self, url: str, **kwargs) -> httpx.Response:
562
+ """HEAD 请求"""
563
+ return await self._request('HEAD', url, **kwargs)
564
+
565
+ async def options(self, url: str, **kwargs) -> httpx.Response:
566
+ """OPTIONS 请求"""
567
+ return await self._request('OPTIONS', url, **kwargs)
568
+
569
+
570
+ # ============ 使用示例 ============
571
+ """
572
+ 使用示例:
573
+
574
+ 1. 基本使用(自动从 request_context 获取认证信息):
575
+
576
+ from huace_aigc_auth_client.auth_request import auth_request
577
+ from huace_aigc_auth_client.user_context import set_request_context
578
+
579
+ # 设置请求上下文
580
+ set_request_context(
581
+ app_id='your-app-id',
582
+ app_secret='your-app-secret',
583
+ token='user-access-token',
584
+ ip_address='192.168.1.1',
585
+ user_agent='Mozilla/5.0...',
586
+ trace_id='trace-123'
587
+ )
588
+
589
+ # 发起请求(会自动添加认证信息)
590
+ response = auth_request('GET', 'https://api.example.com/data')
591
+ print(response.json())
592
+
593
+
594
+ 2. 带参数的请求:
595
+
596
+ # GET 请求带查询参数
597
+ response = auth_request(
598
+ 'GET',
599
+ 'https://api.example.com/users',
600
+ params={'page': 1, 'size': 10}
601
+ )
602
+
603
+ # POST 请求带 JSON 数据
604
+ response = auth_request(
605
+ 'POST',
606
+ 'https://api.example.com/users',
607
+ json={'name': 'John', 'email': 'john@example.com'}
608
+ )
609
+
610
+ # POST 请求带表单数据
611
+ response = auth_request(
612
+ 'POST',
613
+ 'https://api.example.com/upload',
614
+ data={'field1': 'value1', 'field2': 'value2'}
615
+ )
616
+
617
+
618
+ 3. 覆盖默认 headers:
619
+
620
+ # 可以手动指定 headers,会与自动添加的 headers 合并
621
+ response = auth_request(
622
+ 'GET',
623
+ 'https://api.example.com/data',
624
+ headers={'Custom-Header': 'custom-value'}
625
+ )
626
+
627
+
628
+ 4. 与 API 统计收集器配合使用:
629
+
630
+ from huace_aigc_auth_client.api_stats_collector import init_api_stats_collector
631
+ from huace_aigc_auth_client.auth_request import auth_request
632
+ from huace_aigc_auth_client.user_context import set_request_context
633
+
634
+ # 初始化统计收集器
635
+ init_api_stats_collector(
636
+ api_url='http://auth.example.com/api/sdk',
637
+ app_id='your-app-id',
638
+ app_secret='your-app-secret',
639
+ enabled=True
640
+ )
641
+
642
+ # 设置请求上下文
643
+ set_request_context(
644
+ app_id='your-app-id',
645
+ app_secret='your-app-secret',
646
+ token='user-access-token'
647
+ )
648
+
649
+ # 发起请求(会自动上报统计)
650
+ response = auth_request('GET', 'https://api.example.com/data')
651
+
652
+
653
+ 5. 使用 httpx 异步请求(需要安装 httpx):
654
+
655
+ from huace_aigc_auth_client.auth_request import async_auth_request, AsyncAuthClient
656
+ from huace_aigc_auth_client.user_context import set_request_context
657
+ import asyncio
658
+
659
+ # 设置请求上下文
660
+ set_request_context(
661
+ app_id='your-app-id',
662
+ app_secret='your-app-secret',
663
+ token='user-access-token'
664
+ )
665
+
666
+ # 方式1:使用 async_auth_request 函数
667
+ async def example1():
668
+ response = await async_auth_request('GET', 'https://api.example.com/data')
669
+ print(response.json())
670
+
671
+ # 方式2:使用 AsyncAuthClient(推荐用于多个请求)
672
+ async def example2():
673
+ async with AsyncAuthClient(timeout=10.0) as client:
674
+ # POST 请求带 JSON
675
+ response = await client.post(
676
+ 'https://api.example.com/users',
677
+ json={'name': 'John', 'email': 'john@example.com'}
678
+ )
679
+ print(response.json())
680
+
681
+ # GET 请求带参数
682
+ response = await client.get(
683
+ 'https://api.example.com/users',
684
+ params={'page': 1, 'size': 10}
685
+ )
686
+ print(response.json())
687
+
688
+ # 运行
689
+ asyncio.run(example1())
690
+ asyncio.run(example2())
691
+ """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: huace-aigc-auth-client
3
- Version: 1.1.31
3
+ Version: 1.1.33
4
4
  Summary: 华策AIGC Auth Client - 提供 Token 验证、用户信息获取、权限检查、旧系统接入等功能
5
5
  Author-email: Huace <support@huace.com>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "huace-aigc-auth-client"
7
- version = "1.1.31"
7
+ version = "1.1.33"
8
8
  description = "华策AIGC Auth Client - 提供 Token 验证、用户信息获取、权限检查、旧系统接入等功能"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.7"
@@ -1,324 +0,0 @@
1
- """
2
- 认证请求封装模块
3
- 提供对 requests.request 的封装,自动添加认证信息和统计上报
4
- """
5
- import time
6
- import logging
7
- from typing import Optional, Dict, Any, Union
8
- import requests
9
- from requests import Response
10
-
11
- from .user_context import get_request_context
12
- from .api_stats_collector import get_api_stats_collector
13
-
14
- logger = logging.getLogger(__name__)
15
- def setLogger(log):
16
- """
17
- 统一设置所有模块的 logger
18
-
19
- Args:
20
- log: logging.Logger 实例
21
- """
22
- global logger
23
- logger = log
24
-
25
- def auth_request(
26
- method: str,
27
- url: str,
28
- params: Optional[Dict[str, Any]] = None,
29
- data: Optional[Union[Dict[str, Any], str, bytes]] = None,
30
- json: Optional[Dict[str, Any]] = None,
31
- headers: Optional[Dict[str, str]] = None,
32
- cookies: Optional[Dict[str, str]] = None,
33
- files: Optional[Dict[str, Any]] = None,
34
- auth: Optional[tuple] = None,
35
- timeout: Optional[Union[float, tuple]] = None,
36
- allow_redirects: bool = True,
37
- proxies: Optional[Dict[str, str]] = None,
38
- verify: Optional[Union[bool, str]] = None,
39
- stream: bool = False,
40
- cert: Optional[Union[str, tuple]] = None,
41
- **kwargs
42
- ) -> Response:
43
- """
44
- 认证请求封装函数
45
-
46
- 基本参数与 requests.request 一致,会自动从 request_context 中获取认证信息并添加到请求头
47
-
48
- Args:
49
- method: HTTP 方法 (GET, POST, PUT, DELETE 等)
50
- url: 请求 URL
51
- params: URL 查询参数
52
- data: 请求体数据 (form-data 或 raw)
53
- json: JSON 请求体数据
54
- headers: 请求头(会自动添加认证相关的头)
55
- cookies: Cookies
56
- files: 文件上传
57
- auth: HTTP 认证元组
58
- timeout: 超时时间(秒)
59
- allow_redirects: 是否允许重定向
60
- proxies: 代理配置
61
- verify: SSL 证书验证
62
- stream: 是否流式响应
63
- cert: 客户端证书
64
- **kwargs: 其他 requests.request 支持的参数
65
-
66
- Returns:
67
- Response: 响应对象
68
-
69
- 自动添加的请求头(如果在 request_context 中存在):
70
- - X-App-ID: 应用ID
71
- - X-App-Secret: 应用密钥
72
- - Authorization: Bearer token
73
- - x-real-ip: 客户端真实IP
74
- - user-agent: User Agent
75
- - X-Trace-ID: 追踪ID
76
- """
77
- # 初始化 headers
78
- if headers is None:
79
- headers = {}
80
- else:
81
- headers = headers.copy() # 避免修改原始 headers
82
-
83
- # 从 request_context 获取认证信息
84
- request_context = get_request_context()
85
-
86
- if request_context:
87
- # 添加应用ID
88
- app_id = request_context.get('app_id')
89
- if app_id is not None:
90
- headers['X-App-ID'] = str(app_id)
91
-
92
- # 添加应用密钥
93
- app_secret = request_context.get('app_secret')
94
- if app_secret:
95
- headers['X-App-Secret'] = app_secret
96
-
97
- # 添加认证令牌
98
- token = request_context.get('token')
99
- if token:
100
- headers['Authorization'] = f'Bearer {token}'
101
-
102
- # 添加客户端IP
103
- ip_address = request_context.get('ip_address')
104
- if ip_address:
105
- headers['x-real-ip'] = ip_address
106
-
107
- # 添加 User Agent
108
- user_agent = request_context.get('user_agent')
109
- if user_agent:
110
- headers['user-agent'] = user_agent
111
-
112
- # 添加追踪ID
113
- trace_id = request_context.get('trace_id')
114
- if trace_id:
115
- headers['X-Trace-ID'] = trace_id
116
-
117
- # 记录开始时间
118
- start_time = time.time()
119
- response = None
120
- error_message = None
121
-
122
- try:
123
- # 执行请求
124
- logger.info(f"发起认证请求: {method} {url} with headers={headers} params={params} json={json} data={data}")
125
- response = requests.request(
126
- method=method,
127
- url=url,
128
- params=params,
129
- data=data,
130
- json=json,
131
- headers=headers,
132
- cookies=cookies,
133
- files=files,
134
- auth=auth,
135
- timeout=timeout,
136
- allow_redirects=allow_redirects,
137
- proxies=proxies,
138
- verify=verify,
139
- stream=stream,
140
- cert=cert,
141
- **kwargs
142
- )
143
- logger.info(f"认证请求响应: {method} {url} 状态码: {response.status_code}")
144
- return response
145
-
146
- except Exception as e:
147
- error_message = str(e)
148
- logger.error(f"认证请求失败: {method} {url} 错误: {error_message}")
149
- raise
150
-
151
- finally:
152
- # 计算响应时间
153
- response_time = time.time() - start_time
154
-
155
- # 上报统计信息
156
- _report_stats(
157
- url=url,
158
- method=method,
159
- response=response,
160
- response_time=response_time,
161
- error_message=error_message,
162
- request_context=request_context,
163
- headers=headers,
164
- params=params,
165
- json_data=json,
166
- form_data=data
167
- )
168
-
169
-
170
- def _report_stats(
171
- url: str,
172
- method: str,
173
- response: Optional[Response],
174
- response_time: float,
175
- error_message: Optional[str],
176
- request_context: Optional[Dict[str, Any]],
177
- headers: Optional[Dict[str, str]],
178
- params: Optional[Dict[str, Any]],
179
- json_data: Optional[Dict[str, Any]],
180
- form_data: Optional[Union[Dict[str, Any], str, bytes]]
181
- ):
182
- """
183
- 上报统计信息到远程服务
184
-
185
- Args:
186
- url: 请求 URL
187
- method: HTTP 方法
188
- response: 响应对象
189
- response_time: 响应时间
190
- error_message: 错误信息
191
- request_context: 请求上下文
192
- params: 查询参数
193
- json_data: JSON 数据
194
- form_data: 表单数据
195
- """
196
- try:
197
- # 获取统计收集器
198
- collector = get_api_stats_collector()
199
- if not collector:
200
- return
201
-
202
- # 获取 token
203
- token = request_context.get('token') if request_context else None
204
- if not token:
205
- return
206
-
207
- # 解析 URL 获取路径
208
- from urllib.parse import urlparse
209
- parsed_url = urlparse(url)
210
- api_path = parsed_url.path or '/'
211
-
212
- # 获取状态码
213
- status_code = response.status_code if response else 500
214
-
215
- # 构建请求参数(与 api_stats_collector 格式一致)
216
- request_params = {
217
- 'query_params': params or {},
218
- 'headers': headers
219
- }
220
-
221
- # 添加请求体数据
222
- if json_data:
223
- request_params['request_body'] = json_data
224
- elif isinstance(form_data, dict):
225
- request_params['form_params'] = form_data
226
-
227
- # 收集统计
228
- collector.collect(
229
- api_path=api_path,
230
- api_method=method.upper(),
231
- status_code=status_code,
232
- response_time=response_time,
233
- token=token,
234
- error_message=error_message,
235
- request_params=request_params
236
- )
237
-
238
- except Exception as e:
239
- # 静默失败,不影响主流程
240
- logger.debug(f"统计上报失败: {e}")
241
-
242
-
243
- # ============ 使用示例 ============
244
- """
245
- 使用示例:
246
-
247
- 1. 基本使用(自动从 request_context 获取认证信息):
248
-
249
- from huace_aigc_auth_client.auth_request import auth_request
250
- from huace_aigc_auth_client.user_context import set_request_context
251
-
252
- # 设置请求上下文
253
- set_request_context(
254
- app_id='your-app-id',
255
- app_secret='your-app-secret',
256
- token='user-access-token',
257
- ip_address='192.168.1.1',
258
- user_agent='Mozilla/5.0...',
259
- trace_id='trace-123'
260
- )
261
-
262
- # 发起请求(会自动添加认证信息)
263
- response = auth_request('GET', 'https://api.example.com/data')
264
- print(response.json())
265
-
266
-
267
- 2. 带参数的请求:
268
-
269
- # GET 请求带查询参数
270
- response = auth_request(
271
- 'GET',
272
- 'https://api.example.com/users',
273
- params={'page': 1, 'size': 10}
274
- )
275
-
276
- # POST 请求带 JSON 数据
277
- response = auth_request(
278
- 'POST',
279
- 'https://api.example.com/users',
280
- json={'name': 'John', 'email': 'john@example.com'}
281
- )
282
-
283
- # POST 请求带表单数据
284
- response = auth_request(
285
- 'POST',
286
- 'https://api.example.com/upload',
287
- data={'field1': 'value1', 'field2': 'value2'}
288
- )
289
-
290
-
291
- 3. 覆盖默认 headers:
292
-
293
- # 可以手动指定 headers,会与自动添加的 headers 合并
294
- response = auth_request(
295
- 'GET',
296
- 'https://api.example.com/data',
297
- headers={'Custom-Header': 'custom-value'}
298
- )
299
-
300
-
301
- 4. 与 API 统计收集器配合使用:
302
-
303
- from huace_aigc_auth_client.api_stats_collector import init_api_stats_collector
304
- from huace_aigc_auth_client.auth_request import auth_request
305
- from huace_aigc_auth_client.user_context import set_request_context
306
-
307
- # 初始化统计收集器
308
- init_api_stats_collector(
309
- api_url='http://auth.example.com/api/sdk',
310
- app_id='your-app-id',
311
- app_secret='your-app-secret',
312
- enabled=True
313
- )
314
-
315
- # 设置请求上下文
316
- set_request_context(
317
- app_id='your-app-id',
318
- app_secret='your-app-secret',
319
- token='user-access-token'
320
- )
321
-
322
- # 发起请求(会自动上报统计)
323
- response = auth_request('GET', 'https://api.example.com/data')
324
- """