我目前正在尝试使用运行到Django REST框架的multipart / form-data来获取POST请求。我通过交互式API屏幕成功运行了一些测试请求,这些工作正常。然后我尝试将这些转换为使用非基于会话的auth策略,并且我一直有错误。我发送的请求格式如下:
POST /api/logs/ HTTP/1.1
Host: host:8080
Connection: keep-alive
Content-Length: 258
Accept: application/json
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryTOhRsMbL8ak9EMQB
Authorization: Token -token-
------WebKitFormBoundaryx6ThtBDZxZNUCkKl
Content-Disposition: form-data; name="SubmittedAt"
2014-01-23T10:39:00
------WebKitFormBoundaryx6ThtBDZxZNUCkKl
Content-Disposition: form-data; name="Device"
CheeseDevice
------WebKitFormBoundaryx6ThtBDZxZNUCkKl--
可悲的是,结果是(对于我运行的所有请求):
{"Device": ["This field is required."], "SubmittedAt": ["This field is required."], "LogFile": ["This field is required."]}
有趣的是,我已经能够将JSON块发送到端点,并且它们被按预期接受,例如:
POST /api/logs/ HTTP/1.1
Content-Type: application/json
Host: host:8080
Connection: keep-alive
Content-Length: 35
Accept: application/json
Authorization: Token -token-
{
"Device": "CheeseDevice"
}
返回:
{"SubmittedAt": ["This field is required."], "LogFile": ["This field is required."]}
正如预期的那样 - 它实际上接受了Device参数,并且仅在缺少的项目上引发错误。我转而使用JSON,但遗憾的是无法用它上传文件......
提前感谢您的帮助!
编辑:
进一步调查(即:编写一个返回请求数据的视图方法,显示request.DATA由于某种原因没有填充。我用来调试的方法如下:
def test_create(self, request, pk=None):
return Response(request.DATA)
编辑2:
即使进一步调查(并将代码块丢弃到调试框架中)也表明请求正在_perform_form_overloading中被捕获,并且永远不会访问MultiPartParser。不确定为什么会这样,但我会尝试进一步追踪它。
答案 0 :(得分:1)
在深入研究每个级别后,我都能找到......
看起来问题源于行结尾 - 即:我一直使用的libs和请求发送者通过“\ n”(LF)结尾发送内容,而HTTP规范要求“\ r \ n”结局(CR,LF)
这取决于Django核心中的以下代码,在http / multipartparser.py中 - 在parse_boundary_stream中:
header_end = chunk.find(b'\r\n\r\n')
出于开发目的(并且因为它在Django端比在客户端更容易修补...)我已将上面的行切换为:
header_end = chunk.replace("\r\n","\n").find(b'\n\n')
这个更新的代码遵循HTTP / 1.1规范第19.3节关于容忍应用程序和接受LF而不仅仅是CRLF的建议 - 我会试着看看它是否适合包含在Django核心中。< / p>
编辑:
作为参考,该补丁已在GitHub上发布:https://github.com/tr00st/django/commit/9cf6075c113dd27e3743626ab0e18c6616488bd9
答案 1 :(得分:0)
这可能是由于格式错误的多部分发布数据造成的。
您也可能没有安装MultiPartParser
,但我认为不会这样,因为您通常希望在这种情况下看到415 Unsupported Media Type
响应。