If I use chunked transfer encoding with nginx, uwsgi and flask I always get Content-Length
in headers together with Transfer-Encoding: chunked
. However, HTTP 1.1 prohibits this behaviour. I have tried to configure nginx and uwsgi to achieve desired behaviour (no Content-Length
in headers when Transfer-Encoding: chunked
) but without success. Firstly, there is my server and client code:
Server code (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 code (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)
If I run server and try to connect to server with client I get the following output. Server output:
* 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)
Client output:
Response: Hello World!
For now, everything seems alright. In headers, we have Transfer-Encoding
without Content-Length
. Now, I try to incorporate uwsgi (uwsgi.py
):
from server import application
if __name__ == "__main__":
application.run()
I run the following command:
$ uwsgi --http-socket localhost:5000 -w wsgi
The output is the same as in the previous attempt. Therefore, still as expected. Now, I will try to deploy nginx. My uwsgi configuration (uwsgi.ini
):
[uwsgi]
module = wsgi
master = true
processes = 5
socket = /tmp/flask.sock
chmod-socket = 777
vacuum = true
die-on-term = true
My nginx configuration (/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;
}
}
I start nginx and then I run:
$ uwsgi --ini uwsgi.ini --wsgi-manage-chunked-input --http-raw-body --http-auto-chunked --http-chunked-input
Now, the output contains 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)
I try different settings for nginx: proxy_request_buffering
, proxy_buffering
, proxy_http_version
and chunked_transfer_encoding
in the server
and location
context without success. I added X-Accel-Buffering: no
to headers but it did not solve the problem. Also, I tried different options for uwsgi: wsgi-manage-chunked-input
, http-raw-body
, http-auto-chunked
, http-chunked-input
without achieving desired behaviour (Content-Length
is still present in headers with Transfer-Encoding: chunked
).
I use the following versions of flask, uwsgi and nginx:
Flask==0.12.2
uWSGI===2.1-dev-f74553db
nginx 1.12.2-2
Any idea what can be wrong? Thanks.