rate_limit_view.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. # coding=utf-8
  2. """
  3. 应用 API 限流视图
  4. 提供限流配置的 CRUD API
  5. """
  6. from django.utils.translation import gettext as _
  7. from rest_framework.request import Request
  8. from rest_framework.views import APIView
  9. from common.auth import TokenAuth
  10. from common.exception.app_exception import AppApiException
  11. from common.result import result
  12. from application.models.rate_limit import RateLimit, RateLimitType
  13. from application.models.application import Application
  14. class RateLimitView(APIView):
  15. """应用 API 限流管理"""
  16. authentication_classes = [TokenAuth]
  17. class Get(APIView):
  18. """获取应用限流配置"""
  19. authentication_classes = [TokenAuth]
  20. def get(self, request: Request, application_id: str):
  21. try:
  22. application = Application.objects.get(id=application_id)
  23. except Application.DoesNotExist:
  24. raise AppApiException(404, _('应用不存在'))
  25. try:
  26. rate_limit = RateLimit.objects.get(application=application)
  27. data = {
  28. 'id': str(rate_limit.id),
  29. 'application_id': str(rate_limit.application_id),
  30. 'is_enabled': rate_limit.is_enabled,
  31. 'rate_type': rate_limit.rate_type,
  32. 'max_requests': rate_limit.max_requests,
  33. 'burst_size': rate_limit.burst_size,
  34. 'window_seconds': rate_limit.window_seconds,
  35. 'create_time': rate_limit.create_time.isoformat() if rate_limit.create_time else None,
  36. 'update_time': rate_limit.update_time.isoformat() if rate_limit.update_time else None,
  37. }
  38. except RateLimit.DoesNotExist:
  39. data = {
  40. 'application_id': application_id,
  41. 'is_enabled': False,
  42. 'rate_type': 'QPM',
  43. 'max_requests': 60,
  44. 'burst_size': 10,
  45. 'window_seconds': 60,
  46. }
  47. return result.success(data)
  48. class Update(APIView):
  49. """更新应用限流配置"""
  50. authentication_classes = [TokenAuth]
  51. def put(self, request: Request, application_id: str):
  52. try:
  53. application = Application.objects.get(id=application_id)
  54. except Application.DoesNotExist:
  55. raise AppApiException(404, _('应用不存在'))
  56. is_enabled = request.data.get('is_enabled', False)
  57. rate_type = request.data.get('rate_type', 'QPM')
  58. max_requests = request.data.get('max_requests', 60)
  59. burst_size = request.data.get('burst_size', 10)
  60. window_seconds = request.data.get('window_seconds', 60)
  61. # 验证参数
  62. if rate_type not in [t[0] for t in RateLimitType.choices]:
  63. raise AppApiException(400, _('无效的限流类型'))
  64. if max_requests <= 0:
  65. raise AppApiException(400, _('最大请求数必须大于0'))
  66. if window_seconds <= 0:
  67. raise AppApiException(400, _('时间窗口必须大于0'))
  68. rate_limit, created = RateLimit.objects.update_or_create(
  69. application=application,
  70. defaults={
  71. 'is_enabled': is_enabled,
  72. 'rate_type': rate_type,
  73. 'max_requests': max_requests,
  74. 'burst_size': burst_size,
  75. 'window_seconds': window_seconds,
  76. }
  77. )
  78. return result.success({
  79. 'id': str(rate_limit.id),
  80. 'application_id': str(rate_limit.application_id),
  81. 'is_enabled': rate_limit.is_enabled,
  82. 'rate_type': rate_limit.rate_type,
  83. 'max_requests': rate_limit.max_requests,
  84. 'burst_size': rate_limit.burst_size,
  85. 'window_seconds': rate_limit.window_seconds,
  86. 'create_time': rate_limit.create_time.isoformat() if rate_limit.create_time else None,
  87. 'update_time': rate_limit.update_time.isoformat() if rate_limit.update_time else None,
  88. })
  89. class Reset(APIView):
  90. """重置应用限流计数"""
  91. authentication_classes = [TokenAuth]
  92. def post(self, request: Request, application_id: str):
  93. try:
  94. application = Application.objects.get(id=application_id)
  95. except Application.DoesNotExist:
  96. raise AppApiException(404, _('应用不存在'))
  97. # 这里可以重置内存中的限流计数
  98. # 实际实现需要访问 RateLimitMiddleware 的实例
  99. return result.success({'message': '限流计数已重置'})