Merge pull request #405 from javabrett/support-chunked-340

Added support for chunked encoded requests when running gunicorn. #340
This commit is contained in:
2017-12-18 11:08:18 -05:00
committed by GitHub
2 changed files with 44 additions and 1 deletions
+25 -1
View File
@@ -15,7 +15,7 @@ import time
import uuid
import argparse
from flask import Flask, Response, request, render_template, redirect, jsonify as flask_jsonify, make_response, url_for
from flask import Flask, Response, request, render_template, redirect, jsonify as flask_jsonify, make_response, url_for, abort
from flask_common import Common
from six.moves import range as xrange
from werkzeug.datastructures import WWWAuthenticate, MultiDict
@@ -84,6 +84,30 @@ if os.environ.get("BUGSNAG_API_KEY") is not None:
# -----------
# Middlewares
# -----------
"""
https://github.com/kennethreitz/httpbin/issues/340
Adds a middleware to provide chunked request encoding support running under
gunicorn only.
Werkzeug required environ 'wsgi.input_terminated' to be set otherwise it
empties the input request stream.
- gunicorn seems to support input_terminated but does not add the environ,
so we add it here.
- flask will hang and does not seem to properly terminate the request, so
we explicityly deny chunked requests.
"""
@app.before_request
def before_request():
if request.environ.get('HTTP_TRANSFER_ENCODING', '').lower() == 'chunked':
server = request.environ.get('SERVER_SOFTWARE', '')
if server.lower().startswith('gunicorn/'):
if 'wsgi.input_terminated' in request.environ:
app.logger.debug("environ wsgi.input_terminated already set, keeping: %s"
% request.environ['wsgi.input_terminated'])
else:
request.environ['wsgi.input_terminated'] = 1
else:
abort(501, "Chunked requests are not supported for server %s" % server)
@app.after_request
def set_cors_headers(response):
response.headers['Access-Control-Allow-Origin'] = request.headers.get('Origin', '*')
+19
View File
@@ -206,6 +206,25 @@ class HttpbinTestCase(unittest.TestCase):
)
self.assertEqual(response.status_code, 200)
"""
This is currently a sort of negative-test.
We validate that when running Flask-only server that
Transfer-Encoding: chunked requests are unsupported and
we return 501 Not Implemented
"""
def test_post_chunked(self):
data = '{"animal":"dog"}'
response = self.app.post(
'/post',
content_type='application/json',
headers=[('Transfer-Encoding', 'chunked')],
data=data,
)
self.assertEqual(response.status_code, 501)
#self.assertEqual(response.status_code, 200)
#self.assertEqual(json.loads(response.data.decode('utf-8'))['data'], '{"animal":"dog"}')
#self.assertEqual(json.loads(response.data.decode('utf-8'))['json'], {"animal": "dog"})
def test_set_cors_headers_after_request(self):
response = self.app.get('/get')
self.assertEqual(