Cri*_*lho 4 python apache django http
当 django 使用 mod_wsgi 部署在 apache 上时。它似乎以一种非常奇怪的方式处理不完整或取消的请求。
如果客户端取消了请求,被取消的请求在django上并没有被取消,比如你上传一个大文件,显然请求的body会被实际流式传输,所以django在读取body的时候,客户端取消请求,它仍然被处理(只是不完整)并且从不注意到实际的请求取消操作。
这是来自 apache 的一个日志示例,当请求被取消时。[Fri May 01 22:05:51.055968 2015] [:error] [pid 31609] (70008) 部分结果有效但处理不完整:[client 172.31.43.91:3645] mod_wsgi (pid=31609):无法获取存储桶旅请求。
然后在 django 代码上,实际的 POST 字典永远不会构建(因为请求不完整,但它到达 django 并被处理,好像它有数据一样),因此 django 在尝试获取数据时将失败(并返回丢失的 XX字段错误,或者逻辑如何处理它们)
最后,当 django 尝试写回响应时,它显然会失败,并且客户端已经关闭了连接。
这种情况经常发生在用作移动应用程序的 REST 服务端点的请求上。移动应用程序上传大文件,因此在应用程序挂起/关闭时取消请求,但服务器似乎总是收到部分请求。
发生这种情况时的完整日志如下所示:
[Fri May 01 22:05:51.055968 2015] [:error] [pid 31609] (70008) 部分结果有效但处理不完整:[client 172.31.43.91:3645] mod_wsgi (pid=31609):无法获取存储桶旅请求。
[Fri May 01 22:05:51.062690 2015] [:error] [pid 10580] 一些与此处丢失数据相关的错误消息
[Fri May 01 22:05:51.068790 2015] [:error] [pid 10580] [remote 172.31.43.91:0] mod_wsgi (pid=10580):处理 WSGI 脚本“some-path/wsgi.py”时发生异常
[Fri May 01 22:05:51.068827 2015] [:error] [pid 10580] [remote 172.31.43.91:0] IOError:写入数据失败
现在最后一个问题是,有没有办法检测这种不完整的请求并相应地处理它,而不是稍后因缺少所需数据而失败?
在读取请求内容时,如果没有读取到所需长度的内容,那么 WSGI 层会在wsgi.input.read()被调用时引发IOError异常。这可以按原样在 Django 中传递,或者在更新的版本中更改为不同的派生IOError异常类型,称为UnreadablePostError.
当您的应用程序代码没有专门检查损坏的请求内容并处理该异常类型时,它会反向传播并由 Django 作为未处理的异常进行处理。此时 Django 将尝试编写 500 错误响应。当由 WSGI 层写入时,它将因连接已关闭而失败,这只能通过实际尝试写入响应来检测。
所以 Django 不应该给你不完整的 POST 数据,而是应该引发一个异常。
至于是否有更好的处理方式,答案是否定的。由于 WSGI 规范基于阻塞模型,因此不可能真正以干净的方式检测和处理断开的连接。人们需要切换到 ASYNC Web 服务器和框架才能更好地处理它,这意味着不能使用 WSGI 或 Django。
FWIW,过去曾在 mod_wsgi 邮件列表上讨论过断开连接的问题。因此,您可能会转到 Google 网上论坛并使用“连接断开”或“连接失败”或“连接关闭”等搜索词在档案中搜索列表,看看您能找到什么。
| 归档时间: |
|
| 查看次数: |
4842 次 |
| 最近记录: |