Django - 第二次发送 OPTIONS 请求会将正文数据附加到请求方法

Posted

技术标签:

【中文标题】Django - 第二次发送 OPTIONS 请求会将正文数据附加到请求方法【英文标题】:Django - Sending OPTIONS request second time will append body data to request method 【发布时间】:2019-05-23 11:11:26 【问题描述】:

问题是当正文中有内​​容使用 OPTIONS 方法时,第二个请求总是会失败,并显示消息 Method Not Allowed。打印日志,显示方法变成了""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',
]

请求方法:OPTIONSPOST

请求头:

Content-Type: application/json
Origin: http://google.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER,Content-Type

请求正文:

"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 发送任何其他请求。它总是会返回 Method Not Allowed,即使它是我使用的不同方法。

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。这个问题没有发生。

【问题讨论】:

【参考方案1】:

更新到 Django>=2.1.5 将解决此问题。这是由于这个问题:HTTP server doesn't clear previous request data in keep-alive connection

问题是当有OPTIONS 请求时,runserver 的 WSGI 服务器的实现没有消耗请求内容。并且通过保持连接,剩余的数据被读取为后续请求的内容。

【讨论】:

以上是关于Django - 第二次发送 OPTIONS 请求会将正文数据附加到请求方法的主要内容,如果未能解决你的问题,请参考以下文章

layui跨域问题

后台接口总是请求两次

使用 angular 向 django-rest 发送 DELETE 请求被解释为 OPTIONS

js动态添加option 第一次能添加成功,第二次在请求的时候就 Cannot read property 'options' of null

Django-csrf中间件

Django REST:OPTIONS 请求注册为 PUT