Django - 第二次发送 OPTIONS 请求会将 body 数据附加到请求方法
Django - Sending OPTIONS request second time will append body data to request method
问题是当 body 中的内容使用 OPTIONS 方法时,第二个请求将始终失败并显示消息 不允许使用方法。打印日志显示方法变成了"{"username":"test","password":"test"}POST /member/login/ HTTP/1.1" 405 111
。问题是当服务器重新启动时,第一个 OPTIONS 请求将正常通过。仅尝试使用 POST 并且效果很好。只有 OPTIONS 有这个问题。
ENV 详细信息:python:3.6.5,django:2.1.3,drf:3.9.0,django-cors-headers:2.4.0
views.py(只显示装饰,因为它没有进入块内):
@csrf_exempt
@api_view(['POST'])
@authentication_classes([])
@permission_classes([AllowAny])
def member_login(request):
pass
中间件:
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
请求方法:OPTIONS和POST
请求header:
Content-Type: application/json
Origin: http://google.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER,Content-Type
请求body:
{"username":"superuser","password":"pass1234"}
发送 OPTIONS 请求 2 次后:
INFO 2018-12-25 02:26:03,585 "OPTIONS /member/login/ HTTP/1.1" 200 0
WARNING 2018-12-25 02:26:10,180 Method Not Allowed: /member/login/
WARNING 2018-12-25 02:26:10,182 "{"username":"superuser","password":"pass1234"}OPTIONS /member/login/ HTTP/1.1" 405 98
收到方法不允许的错误后,无法向 api 发送任何其他请求。它总是 return 不允许的方法 即使它是我使用的不同方法。
WARNING 2018-12-25 02:30:57,939 Method Not Allowed: /member/login/
WARNING 2018-12-25 02:30:57,940 "{"username":"superuser","password":"pass1234"}POST /member/login/ HTTP/1.1" 405 95
WARNING 2018-12-25 02:30:58,603 Method Not Allowed: /member/login/
WARNING 2018-12-25 02:30:58,603 "{"username":"superuser","password":"pass1234"}POST /member/login/ HTTP/1.1" 405 95
WARNING 2018-12-25 02:30:59,684 Method Not Allowed: /member/login/
WARNING 2018-12-25 02:30:59,685 "{"username":"superuser","password":"pass1234"}POST /member/login/ HTTP/1.1" 405 95
尝试使用旧版本的 Django。这个问题没有发生。
更新到 Django>=2.1.5
将解决此问题。这是由于这个问题:HTTP server doesn't clear previous request data in keep-alive connection
问题是 runserver
的 WSGI 服务器的实现在有 OPTIONS
请求时没有消耗请求内容。通过保持连接,剩余的数据被读取为后续请求的内容。
问题是当 body 中的内容使用 OPTIONS 方法时,第二个请求将始终失败并显示消息 不允许使用方法。打印日志显示方法变成了"{"username":"test","password":"test"}POST /member/login/ HTTP/1.1" 405 111
。问题是当服务器重新启动时,第一个 OPTIONS 请求将正常通过。仅尝试使用 POST 并且效果很好。只有 OPTIONS 有这个问题。
ENV 详细信息:python:3.6.5,django:2.1.3,drf:3.9.0,django-cors-headers:2.4.0
views.py(只显示装饰,因为它没有进入块内):
@csrf_exempt
@api_view(['POST'])
@authentication_classes([])
@permission_classes([AllowAny])
def member_login(request):
pass
中间件:
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
请求方法:OPTIONS和POST
请求header:
Content-Type: application/json
Origin: http://google.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER,Content-Type
请求body:
{"username":"superuser","password":"pass1234"}
发送 OPTIONS 请求 2 次后:
INFO 2018-12-25 02:26:03,585 "OPTIONS /member/login/ HTTP/1.1" 200 0
WARNING 2018-12-25 02:26:10,180 Method Not Allowed: /member/login/
WARNING 2018-12-25 02:26:10,182 "{"username":"superuser","password":"pass1234"}OPTIONS /member/login/ HTTP/1.1" 405 98
收到方法不允许的错误后,无法向 api 发送任何其他请求。它总是 return 不允许的方法 即使它是我使用的不同方法。
WARNING 2018-12-25 02:30:57,939 Method Not Allowed: /member/login/
WARNING 2018-12-25 02:30:57,940 "{"username":"superuser","password":"pass1234"}POST /member/login/ HTTP/1.1" 405 95
WARNING 2018-12-25 02:30:58,603 Method Not Allowed: /member/login/
WARNING 2018-12-25 02:30:58,603 "{"username":"superuser","password":"pass1234"}POST /member/login/ HTTP/1.1" 405 95
WARNING 2018-12-25 02:30:59,684 Method Not Allowed: /member/login/
WARNING 2018-12-25 02:30:59,685 "{"username":"superuser","password":"pass1234"}POST /member/login/ HTTP/1.1" 405 95
尝试使用旧版本的 Django。这个问题没有发生。
更新到 Django>=2.1.5
将解决此问题。这是由于这个问题:HTTP server doesn't clear previous request data in keep-alive connection
问题是 runserver
的 WSGI 服务器的实现在有 OPTIONS
请求时没有消耗请求内容。通过保持连接,剩余的数据被读取为后续请求的内容。