4

对于我们的 Web 服务,我编写了一些逻辑来防止multipart/form-dataPOST 大于 4mb。

它归结为以下内容(我已经剥离了所有 WebOb 的使用,只是将其简化为普通的 WSGI 代码):

import paste.httpserver

form = """\
<html>
<body>
  <form method="post" enctype="multipart/form-data" action="/">
    <input type="file" name="photopicker" />
    <input type="submit" />
  </form>
</body>
</html>
"""

limit = 4 * 1024 * 1024

def upload_app(environ, start_response):
    if environ['REQUEST_METHOD'] == 'POST':
        if int(environ.get('CONTENT_LENGTH', '0')) > limit:
            start_response('400 Ouch', [('content-type', 'text/plain')])
            return ["Upload is too big!"]
    # elided: consume the file appropriately
    start_response('200 OK', [('content-type', 'text/html')])
    return [form]

paste.httpserver.serve(upload_app, port=7007)

显示的逻辑在单元测试时可以正常工作。但是,当我尝试将大于 4mb 的实际文件发送到此端点时,我在客户端收到了如下错误:

  • Error 101 (net::ERR_CONNECTION_RESET): Unknown error.来自谷歌浏览器
  • The connection to the server was reset while the page was loading.来自火狐

使用 Python 内置wsgirefHTTP 服务器时也会出现同样的错误。

事实:一旦我environ['wsgi.input'].read()在响应 HTTP 400 之前添加,连接重置问题就消失了。当然,这不是一个好的解决方法。它只是显示了当您完全使用输入时会发生什么。

我仔细阅读了HTTP: The Definitive Guide,发现了一些有趣的指南,说明在实现 HTTP 服务器和客户端时仔细管理 TCP 连接的重要性。它继续讨论如何代替close-ing 套接字,而是首选做shutdown,以便客户端有机会做出反应并停止向服务器发送更多数据。

也许我错过了一些防止此类连接重置的关键实现细节。洞察任何人?

要点。

4

1 回答 1

2

发生这种情况是因为您在不读取输入流的情况下丢弃了它,这迫使它关闭。浏览器已经将文件的很大一部分排队等待发送,然后由于服务器强制关闭连接而出现写入错误。

如果不阅读所有输入,我就无法解决这个问题。

我会推荐一些 Javascript 在发送之前测试文件的大小。那么唯一得到错误的人是那些忽略客户端检查的人,因为他们没有 Javascript 或因为他们故意尝试恶意。

于 2010-01-20T08:11:07.493 回答