首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何处理python烧瓶服务器中的"413:请求实体太大“

如何处理python烧瓶服务器中的"413:请求实体太大“
EN

Stack Overflow用户
提问于 2013-10-18 21:20:59
回答 3查看 31.1K关注 0票数 8

我正在使用烧瓶-上传将文件上传到我的烧瓶服务器。允许的最大大小是通过使用flaskext.uploads.patch_request_class(app, 16 * 1024 * 1024)设置的。

我的客户端应用程序(一个单元测试)使用请求来发布一个大文件。

我可以看到,我的服务器返回状态413: Request Entity Too Large的HTTP响应。但是客户端在请求代码中引发异常。

代码语言:javascript
运行
复制
ConnectionError: HTTPConnectionPool(host='api.example.se', port=80): Max retries exceeded with url: /images (Caused by <class 'socket.error'>: [Errno 32] Broken pipe)

我的猜测是,服务器断开重新连接套接字,并将回复发送回客户端。但是,当客户端收到一个中断的发送套接字时,它会引发一个异常并跳过响应。

问题:

  • 我对酒瓶上传和请求的猜测正确吗?
  • 瓶子上传和请求处理413错误正确吗?
  • 当帖子太大时,我是否应该期望我的客户端代码得到一些html?

更新

这里有一个简单的例子,重现了我的问题。

server.py

代码语言:javascript
运行
复制
from flask import Flask, request
app = Flask(__name__)
app.config['MAX_CONTENT_LENGTH'] = 1024

@app.route('/post', methods=('POST',))
def view_post():
    return request.data

app.run(debug=True)

client.py

代码语言:javascript
运行
复制
from tempfile import NamedTemporaryFile
import requests

def post(size):
    print "Post with size %s" % size,
    f = NamedTemporaryFile(delete=False, suffix=".jpg")
    for i in range(0, size):
        f.write("CoDe")
    f.close()

    # Post
    files = {'file': ("tempfile.jpg", open(f.name, 'rb'))}
    r = requests.post("http://127.0.0.1:5000/post", files=files)
    print "gives status code = %s" % r.status_code

post(16)
post(40845)
post(40846)

来自客户的结果

代码语言:javascript
运行
复制
Post with size 16 gives status code = 200
Post with size 40845 gives status code = 413
Post with size 40846
Traceback (most recent call last):
  File "client.py", line 18, in <module>
    post(40846)
  File "client.py", line 13, in post
    r = requests.post("http://127.0.0.1:5000/post", files=files)
  File "/opt/python_env/renter/lib/python2.7/site-packages/requests/api.py", line 88, in post
    return request('post', url, data=data, **kwargs)
  File "/opt/python_env/renter/lib/python2.7/site-packages/requests/api.py", line 44, in request
    return session.request(method=method, url=url, **kwargs)
  File "/opt/python_env/renter/lib/python2.7/site-packages/requests/sessions.py", line 357, in request
    resp = self.send(prep, **send_kwargs)
  File "/opt/python_env/renter/lib/python2.7/site-packages/requests/sessions.py", line 460, in send
    r = adapter.send(request, **kwargs)
  File "/opt/python_env/renter/lib/python2.7/site-packages/requests/adapters.py", line 354, in send
    raise ConnectionError(e)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=5000): Max retries exceeded with url: /post (Caused by <class 'socket.error'>: [Errno 32] Broken pipe)

我的版本

代码语言:javascript
运行
复制
$ pip freeze
Flask==0.10.1
Flask-Mail==0.9.0
Flask-SQLAlchemy==1.0
Flask-Uploads==0.1.3
Jinja2==2.7.1
MarkupSafe==0.18
MySQL-python==1.2.4
Pillow==2.1.0
SQLAlchemy==0.8.2
Werkzeug==0.9.4
blinker==1.3
itsdangerous==0.23
passlib==1.6.1
python-dateutil==2.1
requests==2.0.0
simplejson==3.3.0
six==1.4.1
virtualenv==1.10.1
voluptuous==0.8.1
wsgiref==0.1.2
EN

回答 3

Stack Overflow用户

发布于 2013-10-19 15:29:03

烧瓶正在关闭连接,您可以为413错误设置一个错误处理程序:

代码语言:javascript
运行
复制
@app.errorhandler(413)
def request_entity_too_large(error):
    return 'File Too Large', 413

现在客户机应该得到413错误,请注意,我没有测试这段代码。

更新:

我尝试重新创建413错误,但没有得到ConnectionError异常。

下面是一个简单的例子:

代码语言:javascript
运行
复制
from flask import Flask, request

app = Flask(__name__)

app.config['MAX_CONTENT_LENGTH'] = 1024


@app.route('/post', methods=('POST',))
def view_post():
    return request.data


app.run(debug=True)

运行该文件后,我使用终端测试请求和发送大数据:

代码语言:javascript
运行
复制
>>> import requests
>>> r = requests.post('http://127.0.0.1:5000/post', data={'foo': 'a'})
>>> r
<Response [200]>
>>> r = requests.post('http://127.0.0.1:5000/post', data={'foo': 'a'*10000})
>>> r
<Response [413]>
>>> r.status_code
413
>>> r.content
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">\n<title>413 Request Entity Too Large</title
>\n<h1>Request Entity Too Large</h1>\n<p>The data value transmitted exceeds the capacity limit.</p>\n'

正如您所看到的,我们得到了来自烧瓶413错误的响应,并且请求没有引发异常。

顺便说一句我用的是:

  • 瓶: 0.10.1
  • 请求: 2.0.0
票数 8
EN

Stack Overflow用户

发布于 2013-10-18 21:24:54

HTTP1.1的规范RFC 2616说:

10.4.14 413请求实体太大 服务器拒绝处理请求,因为请求 实体比服务器愿意或能够处理的要大。The 服务器可能关闭连接,以防止客户端继续请求.。 如果条件是临时的,服务器应该包括重试- 后标头字段,以表示它是临时的,以及在什么之后 客户可以再试一次。

这里发生的事情是:烧瓶正在关闭连接,以防止客户端继续上传,这将给您提供Broken pipe错误。

票数 4
EN

Stack Overflow用户

发布于 2019-12-16 07:28:06

基于这个github问题答案(https://github.com/benoitc/gunicorn/issues/1733#issuecomment-377000612)

代码语言:javascript
运行
复制
@app.before_request
def handle_chunking():
    """
    Sets the "wsgi.input_terminated" environment flag, thus enabling
    Werkzeug to pass chunked requests as streams.  The gunicorn server
    should set this, but it's not yet been implemented.
    """

    transfer_encoding = request.headers.get("Transfer-Encoding", None)
    if transfer_encoding == u"chunked":
        request.environ["wsgi.input_terminated"] = True
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19459236

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档