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