DRF之异常捕获源码分析
【一】异常捕获介绍
- Django Rest Framework(DRF)是一个用于构建Web API的强大框架,它提供了一种处理异常的机制,使开发人员能够捕获和处理各种异常情况。
- DRF中的异常捕获类是用于捕获和处理这些异常的关键组件之一。
【二】异常捕获流程分析
# 全局异常处理
# 'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler',
- 通过上述配置
- 当发生异常时,系统会调用该函数进行异常处理。
- 在该函数中,可以执行一些自定义的操作来处理异常
- 比如记录日志、返回统一的错误响应等。
【三】exception_handler源码分析
# exc: 这是引发的异常对象,它是一个Python异常类的实例。
# context: 这是一个字典,包含了有关异常上下文的信息,通常包括请求对象和视图对象等。
def exception_handler(exc, context):
"""
Returns the response that should be used for any given exception.
By default we handle the REST framework `APIException`, and also
Django's built-in `Http404` and `PermissionDenied` exceptions.
Any unhandled exceptions may return `None`, which will cause a 500 error
to be raised.
"""
# exception_handler 函数首先检查异常对象 exc 的类型,然后根据异常类型返回适当的HTTP响应
if isinstance(exc, Http404):
# 如果异常是 Http404 类型(即页面不存在),则将其替换为 DRF 中的 NotFound 异常。
exc = exceptions.NotFound()
elif isinstance(exc, PermissionDenied):
# 如果异常是 PermissionDenied 类型(即权限被拒绝),则将其替换为 DRF 中的 PermissionDenied 异常。
exc = exceptions.PermissionDenied()
# 检查异常是否属于 APIException 类型,这是DRF中异常的基类
# 如果是 APIException 类型
if isinstance(exc, exceptions.APIException):
# 它将为异常设置HTTP响应的头信息(如认证头和重试头)
headers = {}
# 如果异常具有 auth_header 属性,将该属性的值添加到响应的 WWW-Authenticate 头信息中。
# 这通常用于处理身份验证相关的异常。
if getattr(exc, 'auth_header', None):
# 并将异常的详细信息包装在响应数据中
headers['WWW-Authenticate'] = exc.auth_header
# 如果异常具有 wait 属性,将该属性的值添加到响应的 Retry-After 头信息中。
# 这通常用于指示客户端应该等待多长时间后再次尝试请求。
if getattr(exc, 'wait', None):
# 并将异常的详细信息包装在响应数据中
headers['Retry-After'] = '%d' % exc.wait
# 根据异常的 detail 属性创建响应数据。如果 detail 是列表或字典,则直接使用;否则,将其包装在一个字典中
if isinstance(exc.detail, (list, dict)):
data = exc.detail
else:
data = {'detail': exc.detail}
# 调用 set_rollback() 来确保数据库回滚(如果有的话)
# set_rollback(): 这个函数用于确保数据库事务回滚,以防异常发生在数据库事务内部。
set_rollback()
# 返回一个DRF响应对象
return Response(data, status=exc.status_code, headers=headers)
return None
【四】DRF的异常类型源码分析
def _get_error_details(data, default_code=None):
"""
# 将嵌套的数据结构中的潜在翻译字符串或字符串转换为 ErrorDetail 对象。
Descend into a nested data structure, forcing any
lazy translation strings or strings into `ErrorDetail`.
"""
# 处理列表或元组类型的数据。
# 如果数据是列表或元组,它会迭代其中的每个元素
if isinstance(data, (list, tuple)):
# 递归调用 _get_error_details 函数来处理每个元素,并将结果存储在 ret 列表中。
ret = [
_get_error_details(item, default_code) for item in data
]
# 如果原始数据是 ReturnList 类型(DRF中的特殊列表类型),则将结果包装在一个新的 ReturnList 对象中;
if isinstance(data, ReturnList):
# 否则,直接返回 ret 列表。
return ReturnList(ret, serializer=data.serializer)
return ret
# 如果数据是字典,它会迭代其中的每个键值对
elif isinstance(data, dict):
# 递归调用 _get_error_details 函数来处理每个值,并将结果存储在 ret 字典中。
ret = {
key: _get_error_details(value, default_code)
for key, value in data.items()
}
# 如果原始数据是 ReturnDict 类型(DRF中的特殊字典类型)
if isinstance(data, ReturnDict):
# ,则将结果包装在一个新的 ReturnDict 对象中
return ReturnDict(ret, serializer=data.serializer)
# 否则,直接返回 ret 字典
return ret
# 如果数据既不是列表/元组也不是字典,那么它被视为文本数据。
# 这里使用 force_str 函数将数据强制转换为字符串,然后检查是否存在 code 属性。
# 如果存在 code 属性,将其作为错误代码;
# 否则,使用 default_code。
# 然后,创建一个 ErrorDetail 对象,其中包含文本和错误代码,并将其返回。
text = force_str(data)
code = getattr(data, 'code', default_code)
return ErrorDetail(text, code)
# 获取异常详细信息中的错误代码,以便在响应中提供错误信息的标识。
def _get_codes(detail):
# 参数 detail,该参数可以是任何数据类型(通常是嵌套的错误详细信息)。
# 函数首先检查 detail 是否为列表
# 如果是列表,则递归调用 _get_codes 函数处理列表中的每个元素。
if isinstance(detail, list):
return [_get_codes(item) for item in detail]
# 如果 detail 是字典,则递归调用 _get_codes 函数处理字典中的每个值。
elif isinstance(detail, dict):
return {key: _get_codes(value) for key, value in detail.items()}
# 最终,如果 detail 不是列表或字典,而是具有 code 属性的对象,就返回该对象的 code 属性。
return detail.code
# 获取异常详细信息的完整内容,以便在响应中提供详细的错误信息和错误代码。
def _get_full_details(detail):
# 参数 detail,该参数可以是任何数据类型(通常是嵌套的错误详细信息)。
# 函数首先检查 detail 是否为列表,如果是列表,则递归调用 _get_full_details 函数处理列表中的每个元素。
if isinstance(detail, list):
return [_get_full_details(item) for item in detail]
elif isinstance(detail, dict):
# 如果 detail 是字典,则递归调用 _get_full_details 函数处理字典中的每个值。
return {key: _get_full_details(value) for key, value in detail.items()}
# 最终,如果 detail 不是列表或字典,而是具有 code 属性的对象,就创建一个包含 message 和 code 的字典并返回。
return {
'message': detail,
'code': detail.code
}
# 用于表示API异常的详细信息
class ErrorDetail(str):
"""
A string-like object that can additionally have a code.
"""
# 用于存储错误代码,默认为 None。
code = None
# 类的构造函数,它在对象创建时被调用。
# 它接受两个参数:string 是字符串的内容,code 是错误代码。
def __new__(cls, string, code=None):
# 它使用 super().__new__(cls, string) 来创建一个新的字符串对象
self = super().__new__(cls, string)
# 并将错误代码赋值给 self.code。最后,它返回新创建的对象。
self.code = code
return self
# 对象的等于(==)运算符的重载方法。
def __eq__(self, other):
result = super().__eq__(other)
# 它用于比较两个 ErrorDetail 对象是否相等。
if result is NotImplemented:
return NotImplemented
try:
# 如果两个对象的内容相等并且它们的错误代码也相等,返回 True;否则,返回 False。
return result and self.code == other.code
except AttributeError:
return result
# 对象的不等于(!=)运算符的重载方法。
def __ne__(self, other):
# 它使用 __eq__ 方法来实现不等于运算符。
result = self.__eq__(other)
if result is NotImplemented:
return NotImplemented
return not result
# 对象的字符串表示方法,用于返回对象的可打印字符串表示。
# 它返回一个格式化的字符串,包含了字符串内容和错误代码。
def __repr__(self):
return 'ErrorDetail(string=%r, code=%r)' % (
str(self),
self.code,
)
# 对象的哈希方法,用于生成对象的哈希值。
# 它基于字符串内容的哈希值生成对象的哈希值。
def __hash__(self):
return hash(str(self))
# 这个类是所有DRF异常的基类,其他自定义异常应该从这个类继承,并提供特定的 status_code 和 default_detail 属性
class APIException(Exception):
"""
Base class for REST framework exceptions.
Subclasses should provide `.status_code` and `.default_detail` properties.
"""
# 这个属性指定了默认的HTTP状态代码,如果子类没有提供自定义的 status_code,则默认为500(内部服务器错误)。
status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
# 这个属性指定了默认的异常详细信息,它是一个本地化字符串,用于描述异常的内容。
# 在这里,使用了 _() 函数来标记该字符串以进行国际化/本地化处理。
default_detail = _('A server error occurred.')
# 这个属性指定了默认的错误代码,用于标识异常类型。默认为 'error'。
default_code = 'error'
# 类的构造函数,它接受两个可选参数:detail 和 code
def __init__(self, detail=None, code=None):
# 构造函数首先检查这两个参数是否为 None
# 如果是,就将它们设置为默认值(default_detail 和 default_code)。
if detail is None:
detail = self.default_detail
if code is None:
code = self.default_code
# 然后,构造函数调用 _get_error_details 函数来处理 detail 和 code,并将结果存储在 self.detail 属性中。
self.detail = _get_error_details(detail, code)
def __str__(self):
# 返回异常的字符串表示,通常是异常详细信息的字符串表示。
return str(self.detail)
# 获取异常详细信息中的错误代码。
def get_codes(self):
"""
Return only the code part of the error details.
Eg. {"name": ["required"]}
"""
# 它调用 _get_codes 函数来处理 self.detail,并返回结果。
return _get_codes(self.detail)
# 获取异常详细信息的完整内容,包括消息和错误代码。
def get_full_details(self):
"""
Return both the message & code parts of the error details.
Eg. {"name": [{"message": "This field is required.", "code": "required"}]}
"""
# 它调用 _get_full_details 函数来处理 self.detail,并返回结果。
return _get_full_details(self.detail)
# 用于表示API请求中的验证错误,通常与HTTP 400 Bad Request状态一起使用。
class ValidationError(APIException):
# 这个属性指定了 HTTP 400 Bad Request 状态代码,表示请求的内容或参数不符合要求。
status_code = status.HTTP_400_BAD_REQUEST
# 这个属性指定了默认的异常详细信息,用于描述验证失败的原因。它是一个本地化字符串,通常为 "Invalid input."。
default_detail = _('Invalid input.')
# 这个属性指定了默认的错误代码,用于标识验证失败。默认为 'invalid'。
default_code = 'invalid'
# 类的构造函数,它接受两个可选参数:detail 和 code。
def __init__(self, detail=None, code=None):
# 检查这两个参数是否为 None
# 如果是,就将它们设置为默认值(default_detail 和 default_code)。
if detail is None:
detail = self.default_detail
if code is None:
code = self.default_code
# For validation failures, we may collect many errors together,
# so the details should always be coerced to a list if not already.
# 然后,构造函数检查 detail 是否为元组
# 如果是,将其转换为列表;
if isinstance(detail, tuple):
detail = list(detail)
# 如果 detail 既不是字典也不是列表,将其包装成一个列表。
elif not isinstance(detail, dict) and not isinstance(detail, list):
detail = [detail]
# 最后,构造函数调用 _get_error_details 函数来处理 detail 和 code,并将结果存储在 self.detail 属性中。
self.detail = _get_error_details(detail, code)
# 表示解析请求时出现错误,通常对应HTTP 400 Bad Request状态。
# 默认详细信息为 "Malformed request."。
class ParseError(APIException):
status_code = status.HTTP_400_BAD_REQUEST
default_detail = _('Malformed request.')
default_code = 'parse_error'
# 表示身份验证失败,通常对应HTTP 401 Unauthorized状态。
# 默认详细信息为 "Incorrect authentication credentials."。
class AuthenticationFailed(APIException):
status_code = status.HTTP_401_UNAUTHORIZED
default_detail = _('Incorrect authentication credentials.')
default_code = 'authentication_failed'
# 表示未提供身份验证凭据,通常对应HTTP 401 Unauthorized状态。
# 默认详细信息为 "Authentication credentials were not provided."。
class NotAuthenticated(APIException):
status_code = status.HTTP_401_UNAUTHORIZED
default_detail = _('Authentication credentials were not provided.')
default_code = 'not_authenticated'
# 表示没有执行此操作的权限,通常对应HTTP 403 Forbidden状态。
# 默认详细信息为 "You do not have permission to perform this action."。
class PermissionDenied(APIException):
status_code = status.HTTP_403_FORBIDDEN
default_detail = _('You do not have permission to perform this action.')
default_code = 'permission_denied'
# 表示资源未找到,通常对应HTTP 404 Not Found状态。
# 默认详细信息为 "Not found."。
class NotFound(APIException):
status_code = status.HTTP_404_NOT_FOUND
default_detail = _('Not found.')
default_code = 'not_found'
# 表示请求的HTTP方法不允许,通常对应HTTP 405 Method Not Allowed状态。它包括一个额外的参数 method,用于指定不允许的HTTP方法。
# 默认详细信息为 "Method "{method}" not allowed."。
class MethodNotAllowed(APIException):
status_code = status.HTTP_405_METHOD_NOT_ALLOWED
default_detail = _('Method "{method}" not allowed.')
default_code = 'method_not_allowed'
def __init__(self, method, detail=None, code=None):
if detail is None:
detail = force_str(self.default_detail).format(method=method)
super().__init__(detail, code)
# 表示无法满足请求的Accept头部,通常对应HTTP 406 Not Acceptable状态。
# 它包括一个额外的参数 available_renderers,用于指定可用的渲染器。
# 默认详细信息为 "Could not satisfy the request Accept header."。
class NotAcceptable(APIException):
status_code = status.HTTP_406_NOT_ACCEPTABLE
default_detail = _('Could not satisfy the request Accept header.')
default_code = 'not_acceptable'
def __init__(self, detail=None, code=None, available_renderers=None):
self.available_renderers = available_renderers
super().__init__(detail, code)
# 表示请求中包含了不支持的媒体类型(Media Type),通常对应HTTP 415 Unsupported Media Type状态。
# 它包括一个额外的参数 media_type,用于指定不支持的媒体类型。
# 默认详细信息为 "Unsupported media type "{media_type}" in request."。
class UnsupportedMediaType(APIException):
status_code = status.HTTP_415_UNSUPPORTED_MEDIA_TYPE
default_detail = _('Unsupported media type "{media_type}" in request.')
default_code = 'unsupported_media_type'
def __init__(self, media_type, detail=None, code=None):
if detail is None:
detail = force_str(self.default_detail).format(media_type=media_type)
super().__init__(detail, code)
# 表示请求被限速(Throttled),通常对应HTTP 429 Too Many Requests状态。
# 它包括一个额外的参数 wait,用于指定还需等待多少时间才能再次进行请求。
# 默认详细信息为 "Request was throttled.",并且根据 wait 参数动态生成额外的详细信息,用于描述还需等待的时间。
class Throttled(APIException):
status_code = status.HTTP_429_TOO_MANY_REQUESTS
default_detail = _('Request was throttled.')
extra_detail_singular = _('Expected available in {wait} second.')
extra_detail_plural = _('Expected available in {wait} seconds.')
default_code = 'throttled'
def __init__(self, wait=None, detail=None, code=None):
if detail is None:
detail = force_str(self.default_detail)
if wait is not None:
wait = math.ceil(wait)
detail = ' '.join((
detail,
force_str(ngettext(self.extra_detail_singular.format(wait=wait),
self.extra_detail_plural.format(wait=wait),
wait))))
self.wait = wait
super().__init__(detail, code)
# 这个函数是用于处理通用的服务器错误,通常对应HTTP 500 Internal Server Error状态。
# 当服务器发生未处理的异常时,Django会调用这个视图函数。该函数返回一个JSON响应,其中包含一个简单的错误消息,状态代码为HTTP 500。
def server_error(request, *args, **kwargs):
"""
Generic 500 error handler.
"""
data = {
'error': 'Server Error (500)'
}
return JsonResponse(data, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
# 这个函数是用于处理通用的客户端请求错误,通常对应HTTP 400 Bad Request状态。
# 当Django无法处理客户端请求时(例如,请求的数据格式不正确),或者视图中抛出了 ValidationError 异常时,Django会调用这个视图函数。
# 该函数返回一个JSON响应,其中包含一个简单的错误消息,状态代码为HTTP 400。
def bad_request(request, exception, *args, **kwargs):
"""
Generic 400 error handler.
"""
data = {
'error': 'Bad Request (400)'
}
return JsonResponse(data, status=status.HTTP_400_BAD_REQUEST)
【五】自定义异常捕获类
from rest_framework.views import exception_handler
from rest_framework.response import Response
from .common_logger import logger
# 日志记录必要的报错信息
# 记录日志信息必含:用户地址 + 用户ID + 请求地址 + 执行的视图函数 + 异常原因
def common_exception_handler(exc, context):
# 获取请求对象
request = context.get('request')
# 获取视图对象
view = context.get('view')
# 获取请求的IP地址
ip = request.META.get('REMOTE_ADDR')
try:
# 尝试获取用户ID,如果用户未登录,则设置为"未登录用户"
user_id = request.user.id
except:
user_id = "未登录用户"
# 获取请求的完整路径
path = request.get_full_path()
# 将视图对象转换为字符串以记录日志
view_str = str(view)
# 调用默认异常处理函数获取异常响应
res = exception_handler(exc, context)
# 构建错误日志信息
error = f'当前用户地址 : {ip} , 用户ID : {user_id} , 请求地址 : {path} , 执行的视图函数 {view_str} , 异常原因 : {str(exc)}'
# 使用日志记录器记录错误日志
logger.error(error)
if res:
# 如果存在异常响应
if isinstance(res.data, dict):
# 如果异常响应的数据是字典类型,一般是DRF的异常
# DRF 异常:一种是从 res.data 中取/一种是从 data 中取
data = {"code": 999, "msg": res.data.get("detail", "系统错误,请联系管理员")}
else:
# 如果异常响应的数据不是字典类型,通常是其他异常
data = {"code": 888, "msg": str(exc)}
# 返回自定义的异常响应
return Response(data)
【六】DRF自带的响应状态码
from rest_framework import status
# 判断给定的HTTP状态码是否属于信息性状态码,信息性状态码的范围是100到199。
def is_informational(code):
return 100 <= code <= 199
# 判断给定的HTTP状态码是否属于成功状态码,成功状态码的范围是200到299。
def is_success(code):
return 200 <= code <= 299
# 判断给定的HTTP状态码是否属于重定向状态码,重定向状态码的范围是300到399。
def is_redirect(code):
return 300 <= code <= 399
# 判断给定的HTTP状态码是否属于客户端错误状态码,客户端错误状态码的范围是400到499。
def is_client_error(code):
return 400 <= code <= 499
# 判断给定的HTTP状态码是否属于服务器错误状态码,服务器错误状态码的范围是500到599。
def is_server_error(code):
return 500 <= code <= 599
# 1xx(信息性状态码)表示请求已被接受,继续处理。
# 继续。服务器仅接受客户端请求的一部分,等待客户端继续发送请求。
HTTP_100_CONTINUE = 100
# 切换协议。服务器将遵从客户的请求切换协议。
HTTP_101_SWITCHING_PROTOCOLS = 101
# 处理中。服务器正在处理请求,但需要更多时间。
HTTP_102_PROCESSING = 102
# 提前提示。服务器可以将头信息返回给客户端,以提前表示响应可能的形式。
HTTP_103_EARLY_HINTS = 103
# 2xx(成功状态码)表示请求已成功接收、理解、接受。
# OK。请求已成功,请求所希望的响应头或数据体将随此响应返回。
HTTP_200_OK = 200
# 已创建。请求已经被实现,而且有一个新的资源已经依据请求的需要而建立。
HTTP_201_CREATED = 201
# 已接受。服务器已接受请求,但尚未处理。
HTTP_202_ACCEPTED = 202
# 非授权信息。服务器已成功处理了请求,但返回的信息可能来自另一来源。
HTTP_203_NON_AUTHORITATIVE_INFORMATION = 203
# 无内容。服务器成功处理了请求,但没有返回任何内容。
HTTP_204_NO_CONTENT = 204
# 重置内容。服务器成功处理了请求,用户代理必须重置文档视图。
HTTP_205_RESET_CONTENT = 205
# 部分内容。服务器已经成功处理了部分 GET 请求。
HTTP_206_PARTIAL_CONTENT = 206
# 多状态。XML 数据包含可执行的多个状态。
HTTP_207_MULTI_STATUS = 207
# 已报告。资源已在之前的请求中报告,返回的响应应该是被引用资源的当前状态。
HTTP_208_ALREADY_REPORTED = 208
# IM Used。服务器已经满足了对资源的请求,响应是对实体(如 HTML 页面或 JSON 文件)的表示。
HTTP_226_IM_USED = 226
# 3xx(重定向状态码)表示客户必须采取进一步的操作才能完成请求。
# 多种选择。被请求的资源存在多种可供选择的响应。
HTTP_300_MULTIPLE_CHOICES = 300
# 永久移动。请求的资源已被永久移动到新 URI。
HTTP_301_MOVED_PERMANENTLY = 301
# 找到。请求的资源现在临时从不同的 URI 响应请求。
HTTP_302_FOUND = 302
# 参见其他。对应当前请求的响应可以在另一个 URI 上被找到。
HTTP_303_SEE_OTHER = 303
# 未修改。自从上次请求后,请求的资源未被修改过。
HTTP_304_NOT_MODIFIED = 304
# 使用代理。请求的资源必须通过指定的代理才能被访问。
HTTP_305_USE_PROXY = 305
# 保留。该状态码将被任何操作继续执行之前,需要客户端的进一步操作来完成请求。
HTTP_306_RESERVED = 306
# 临时重定向。请求的资源现在临时从不同的 URI 响应请求。
HTTP_307_TEMPORARY_REDIRECT = 307
# 永久重定向。请求的资源已被永久移动到新 URI。
HTTP_308_PERMANENT_REDIRECT = 308
# 4xx(客户端错误状态码)表示客户端看起来可能发生了错误。
# 错误请求。服务器不理解请求的语法。
HTTP_400_BAD_REQUEST = 400
# 未授权。请求要求身份验证。
HTTP_401_UNAUTHORIZED = 401
# 需要付款。保留供将来使用。
HTTP_402_PAYMENT_REQUIRED = 402
# 禁止。服务器拒绝请求。
HTTP_403_FORBIDDEN = 403
# 未找到。服务器找不到请求的资源。
HTTP_404_NOT_FOUND = 404
# 方法不允许。请求中指定的方法不被允许。
HTTP_405_METHOD_NOT_ALLOWED = 405
# 不可接受。服务器只生成不可接受的响应。
HTTP_406_NOT_ACCEPTABLE = 406
# 需要代理身份验证。客户端必须先使用代理认证。
HTTP_407_PROXY_AUTHENTICATION_REQUIRED = 407
# 请求超时。服务器等候请求时发生超时。
HTTP_408_REQUEST_TIMEOUT = 408
# 冲突。请求在当前资源状态下无法执行。
HTTP_409_CONFLICT = 409
# 消失。请求的资源已被永久删除。
HTTP_410_GONE = 410
# 需要长度。服务器拒绝在没有定义 Content-Length 头的情况下接受请求。
HTTP_411_LENGTH_REQUIRED = 411
# 前提条件不满足。请求中给定的前提条件由服务器评估为 false。
HTTP_412_PRECONDITION_FAILED = 412
# 请求实体过大。服务器拒绝处理请求,因为请求实体过大。
HTTP_413_REQUEST_ENTITY_TOO_LARGE = 413
# 请求 URI 过长。服务器拒绝提供服务,因为请求的 URI 过长。
HTTP_414_REQUEST_URI_TOO_LONG = 414
# 不支持的媒体类型。服务器拒绝处理不支持的媒体类型的请求。
HTTP_415_UNSUPPORTED_MEDIA_TYPE = 415
# 请求范围不符合要求。页面无法提供请求的范围。
HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE = 416
# 期望失败。服务器未满足"期望"请求标头字段的要求。
HTTP_417_EXPECTATION_FAILED = 417
# 我是茶壶。服务器拒绝尝试用它不会被烧水的茶壶做咖啡。
HTTP_418_IM_A_TEAPOT = 418
# 误导的请求。请求指向了服务器上不存在的资源。
HTTP_421_MISDIRECTED_REQUEST = 421
# 不可处理的实体。请求格式正确,但由于语义错误而无法满足。
HTTP_422_UNPROCESSABLE_ENTITY = 422
# 已锁定。当前资源被锁定。
HTTP_423_LOCKED = 423
# 依赖失败。由于之前的请求失败,所以此次请求失败。
HTTP_424_FAILED_DEPENDENCY = 424
# 过早。服务器不愿意冒着风险去处理可能重播的请求。
HTTP_425_TOO_EARLY = 425
# 需要升级。客户端应切换到TLS/1.0。
HTTP_426_UPGRADE_REQUIRED = 426
# 先决条件要求。要求先决条件,而请求未满足。
HTTP_428_PRECONDITION_REQUIRED = 428
# 请求过多。用户在给定的时间内发送了太多请求。
HTTP_429_TOO_MANY_REQUESTS = 429
# 请求头字段太大。服务器不愿意处理请求,因为请求头字段太大。
HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE = 431
# 因法律原因不可用。访问资源受到法律限制。
HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS = 451
# 5xx(服务器错误状态码)表示服务器在尝试处理请求时发生错误。
# 内部服务器错误。服务器遇到错误,无法完成请求。
HTTP_500_INTERNAL_SERVER_ERROR = 500
# 未实现。服务器不具备完成请求的功能。
HTTP_501_NOT_IMPLEMENTED = 501
# 错误网关。服务器作为网关或代理,从上游服务器收到了无效的响应。
HTTP_502_BAD_GATEWAY = 502
# 服务不可用。服务器目前无法提供请求所需的服务。
HTTP_503_SERVICE_UNAVAILABLE = 503
# 网关超时。服务器作为网关或代理,未及时从上游服务器接收请求。
HTTP_504_GATEWAY_TIMEOUT = 504
# HTTP 版本不受支持。服务器不支持请求中所用的 HTTP 协议版本。
HTTP_505_HTTP_VERSION_NOT_SUPPORTED = 505
# 内容协商。服务器存在内部配置问题。
HTTP_506_VARIANT_ALSO_NEGOTIATES = 506
# 存储不足。服务器无法存储完成请求所必须的内容。
HTTP_507_INSUFFICIENT_STORAGE = 507
# 检测到循环。服务器检测到无限循环。
HTTP_508_LOOP_DETECTED = 508
# 超出带宽限制。服务器达到带宽限制。
HTTP_509_BANDWIDTH_LIMIT_EXCEEDED = 509
# 扩展未执行。客户端需要进一步执行操作以完成请求。
HTTP_510_NOT_EXTENDED = 510
# 需要网络认证。客户端需要进行网络身份验证才能获得请求的响应。
HTTP_511_NETWORK_AUTHENTICATION_REQUIRED = 511
本文来自博客园,作者:Chimengmeng,转载请注明原文链接:https://www.cnblogs.com/dream-ze/p/17715150.html