如果我使用nginx,uwsgi和flask的分块传输编码,我总是会在Content-Length
的标题中得到Transfer-Encoding: chunked
。但是,HTTP 1.1禁止此行为。我试图配置nginx和uwsgi来实现所需的行为(Content-Length
时标题中没有Transfer-Encoding: chunked
但没有成功。首先,有我的服务器和客户端代码:
服务器代码(server.py
):
from flask import Flask
from flask import request
application = Flask(__name__)
@application.route('/', methods=['PUT'])
def hello():
print(request.headers)
print(request.environ.get('SERVER_PROTOCOL'))
return "Hello World!"
if __name__ == "__main__":
application.run(host='0.0.0.0')
客户端代码(client.py
):
import requests
def get_data():
yield b'This is test file.'
yield b'This is test file.'
r = requests.request(
method='PUT',
url='http://127.0.0.1:5000/',
data=get_data(),
headers={
'Content-type': 'text/plain',
'X-Accel-Buffering': 'no',
}
)
print('Response: ', r.text)
如果我运行服务器并尝试使用客户端连接到服务器,我会得到以下输出。服务器输出:
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
Host: 127.0.0.1:5000
User-Agent: python-requests/2.18.4
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Content-Type: text/plain
X-Accel-Buffering: no
Transfer-Encoding: chunked
HTTP/1.1
[pid: 18455|app: 0|req: 1/1] 127.0.0.1 () {34 vars in 412 bytes} [Wed Jan 17 08:24:53 2018] PUT / => generated 12 bytes in 0 msecs (HTTP/1.1 200) 2 headers in 79 bytes (1 switches on core 0)
客户端输出:
Response: Hello World!
现在,一切似乎都没问题。在标头中,我们Transfer-Encoding
没有Content-Length
。现在,我尝试合并uwsgi(uwsgi.py
):
from server import application
if __name__ == "__main__":
application.run()
我运行以下命令:
$ uwsgi --http-socket localhost:5000 -w wsgi
输出与上一次尝试相同。因此,仍然如预期。现在,我将尝试部署nginx。我的uwsgi配置(uwsgi.ini
):
[uwsgi]
module = wsgi
master = true
processes = 5
socket = /tmp/flask.sock
chmod-socket = 777
vacuum = true
die-on-term = true
我的nginx配置(/etc/nginx/nginx.conf
):
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 5000;
server_name 127.0.0.1;
location / {
include uwsgi_params;
uwsgi_pass unix:/tmp/flask.sock;
proxy_request_buffering off;
proxy_buffering off;
proxy_http_version 1.1;
chunked_transfer_encoding on;
}
proxy_request_buffering off;
proxy_buffering off;
proxy_http_version 1.1;
chunked_transfer_encoding on;
}
}
我启动nginx,然后运行:
$ uwsgi --ini uwsgi.ini --wsgi-manage-chunked-input --http-raw-body --http-auto-chunked --http-chunked-input
现在,输出包含Content-Length
:
Content-Type: text/plain
Content-Length: 36
Host: 127.0.0.1:5000
User-Agent: python-requests/2.18.4
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
X-Accel-Buffering: no
Transfer-Encoding: chunked
HTTP/1.1
[pid: 20220|app: 0|req: 1/1] 127.0.0.1 () {42 vars in 525 bytes} [Wed Jan 17 08:31:39 2018] PUT / => generated 12 bytes in 1 msecs (HTTP/1.1 200) 2 headers in 79 bytes (1 switches on core 0)
我在proxy_request_buffering
和proxy_buffering
上下文中尝试了nginx的不同设置:proxy_http_version
,chunked_transfer_encoding
,server
和location
,但没有成功。我向标题添加了X-Accel-Buffering: no
,但它没有解决问题。此外,我尝试了uwsgi的不同选项:wsgi-manage-chunked-input
,http-raw-body
,http-auto-chunked
,http-chunked-input
,但没有达到预期的行为(Content-Length
仍然存在于{Transfer-Encoding: chunked
的标头中1}})。
我使用以下版本的flask,uwsgi和nginx:
Flask==0.12.2
uWSGI===2.1-dev-f74553db
nginx 1.12.2-2
知道什么是错的吗?感谢。
答案 0 :(得分:0)
我遇到了同样的问题。我的环境是uWSGI 2.0.17,有Nginx和Flask 1.0。当客户端使用Transfer-Encoding:chunked发送请求时,nginx添加了Content-Length。 (虽然这是HTTP / 1.1协议所禁止的。)
我的结论是uWSGI不支持使用分块Tranfer-Encoding的请求。当请求标头仅具有Transfer-Encoding并且还具有Transfer-Encoding和Content-Length时,我的烧瓶应用程序没有获得POST方法的请求主体。
Waitress,python 2和3的wsgi服务器解决了这个问题。如果女服务员收到带有Transfer-Encoding标头的请求,他会忽略它并设置正确的Content-Length。 (参考https://github.com/Pylons/waitress/blob/c18aa5e24e8d96bb64c9454a626147f37a23f0f0/waitress/parser.py#L154)
烧瓶官方文档还建议waitree运行生产烧瓶服务器。 (http://flask.pocoo.org/docs/1.0/tutorial/deploy/)