aiteamutils 0.2.33__py3-none-any.whl → 0.2.34__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
aiteamutils/security.py
CHANGED
@@ -199,7 +199,7 @@ def rate_limit(
|
|
199
199
|
key_func: Optional[Callable] = None
|
200
200
|
):
|
201
201
|
"""Rate limiting 데코레이터."""
|
202
|
-
|
202
|
+
rate_limits: Dict[str, Dict[str, Any]] = {}
|
203
203
|
|
204
204
|
def decorator(func: Callable) -> Callable:
|
205
205
|
@wraps(func)
|
@@ -216,39 +216,56 @@ def rate_limit(
|
|
216
216
|
request = arg
|
217
217
|
break
|
218
218
|
if not request:
|
219
|
-
raise
|
219
|
+
raise CustomException(
|
220
220
|
ErrorCode.INTERNAL_ERROR,
|
221
221
|
detail="Request object not found",
|
222
222
|
source_function="rate_limit"
|
223
223
|
)
|
224
224
|
|
225
|
-
#
|
225
|
+
# 레이트 리밋 키 생성
|
226
226
|
if key_func:
|
227
227
|
rate_limit_key = f"rate_limit:{key_func(request)}"
|
228
228
|
else:
|
229
229
|
client_ip = request.client.host
|
230
230
|
rate_limit_key = f"rate_limit:{client_ip}:{func.__name__}"
|
231
231
|
|
232
|
-
|
233
|
-
|
234
|
-
|
232
|
+
now = datetime.now(UTC)
|
233
|
+
|
234
|
+
# 현재 rate limit 정보 가져오기
|
235
|
+
rate_info = rate_limits.get(rate_limit_key)
|
236
|
+
|
237
|
+
if rate_info is None or (now - rate_info["start_time"]).total_seconds() >= window_seconds:
|
238
|
+
# 새로운 rate limit 설정
|
239
|
+
rate_limits[rate_limit_key] = {
|
240
|
+
"count": 1,
|
241
|
+
"start_time": now
|
242
|
+
}
|
243
|
+
else:
|
244
|
+
# 기존 rate limit 업데이트
|
245
|
+
if rate_info["count"] >= max_requests:
|
246
|
+
# rate limit 초과
|
247
|
+
remaining_seconds = window_seconds - (now - rate_info["start_time"]).total_seconds()
|
235
248
|
raise RateLimitExceeded(
|
236
|
-
detail=
|
249
|
+
detail=rate_limit_key,
|
237
250
|
source_function=func.__name__,
|
238
|
-
remaining_seconds=
|
251
|
+
remaining_seconds=remaining_seconds,
|
239
252
|
max_requests=max_requests,
|
240
253
|
window_seconds=window_seconds
|
241
254
|
)
|
242
|
-
|
255
|
+
rate_info["count"] += 1
|
256
|
+
|
257
|
+
try:
|
258
|
+
# 원래 함수 실행
|
243
259
|
return await func(*args, **kwargs)
|
244
|
-
|
245
|
-
|
260
|
+
except CustomException as e:
|
261
|
+
# CustomException은 그대로 전파
|
246
262
|
raise e
|
247
263
|
except Exception as e:
|
248
|
-
|
264
|
+
# 다른 예외는 INTERNAL_ERROR로 래핑
|
265
|
+
raise CustomException(
|
249
266
|
ErrorCode.INTERNAL_ERROR,
|
250
267
|
detail=str(e),
|
251
|
-
source_function=
|
268
|
+
source_function=func.__name__,
|
252
269
|
original_error=e
|
253
270
|
)
|
254
271
|
|
aiteamutils/version.py
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
"""버전 정보"""
|
2
|
-
__version__ = "0.2.
|
2
|
+
__version__ = "0.2.34"
|
@@ -8,9 +8,9 @@ aiteamutils/database.py,sha256=CaH73g8PPNcmLCz4Xr0DBtNSrLcpRlyt0F1zO5Tigfo,33811
|
|
8
8
|
aiteamutils/dependencies.py,sha256=GgN8sFM7qGNmOfpLaFrhuHOgPlBVXWrEgxv29jxjEgI,4226
|
9
9
|
aiteamutils/enums.py,sha256=ipZi6k_QD5-3QV7Yzv7bnL0MjDz-vqfO9I5L77biMKs,632
|
10
10
|
aiteamutils/exceptions.py,sha256=YV-ISya4wQlHk4twvGo16I5r8h22-tXpn9wa-b3WwDM,15231
|
11
|
-
aiteamutils/security.py,sha256=
|
11
|
+
aiteamutils/security.py,sha256=NHiX0rIznYqMVqSIDFj1u2qjsJb6YFgC0GMjzVjnbWk,15135
|
12
12
|
aiteamutils/validators.py,sha256=3N245cZFjgwtW_KzjESkizx5BBUDaJLbbxfNO4WOFZ0,7764
|
13
|
-
aiteamutils/version.py,sha256=
|
14
|
-
aiteamutils-0.2.
|
15
|
-
aiteamutils-0.2.
|
16
|
-
aiteamutils-0.2.
|
13
|
+
aiteamutils/version.py,sha256=t69ncPrInx6hcKQn1rb-2H6AE0Aas3A-6K--9iJOFlg,42
|
14
|
+
aiteamutils-0.2.34.dist-info/METADATA,sha256=Nq_9Q5465EIAShF1fdxThWkhL5WpELqkea3ffyic28g,1718
|
15
|
+
aiteamutils-0.2.34.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
16
|
+
aiteamutils-0.2.34.dist-info/RECORD,,
|
File without changes
|