diff --git a/bigchaindb/web/server.py b/bigchaindb/web/server.py index 022320d7..91892807 100644 --- a/bigchaindb/web/server.py +++ b/bigchaindb/web/server.py @@ -13,6 +13,7 @@ import gunicorn.app.base from bigchaindb import utils from bigchaindb import Bigchain from bigchaindb.web.routes import add_routes +from bigchaindb.web.strip_content_type_middleware import StripContentTypeMiddleware # TODO: Figure out if we do we need all this boilerplate. @@ -60,6 +61,7 @@ def create_app(*, debug=False, threads=1): """ app = Flask(__name__) + app.wsgi_app = StripContentTypeMiddleware(app.wsgi_app) CORS(app) diff --git a/bigchaindb/web/strip_content_type_middleware.py b/bigchaindb/web/strip_content_type_middleware.py new file mode 100644 index 00000000..953c8b78 --- /dev/null +++ b/bigchaindb/web/strip_content_type_middleware.py @@ -0,0 +1,27 @@ +import logging + +logger = logging.getLogger(__name__) + + +class StripContentTypeMiddleware: + """WSGI middleware to strip Content-Type header for GETs.""" + + def __init__(self, app): + """Create the new middleware. + + Args: + app: a flask application + """ + self.app = app + + def __call__(self, environ, start_response): + """Run the middleware and then call the original WSGI application.""" + + if environ['REQUEST_METHOD'] == 'GET': + try: + del environ['CONTENT_TYPE'] + except KeyError: + pass + else: + logger.debug('Remove header "Content-Type" from GET request') + return self.app(environ, start_response) diff --git a/tests/web/test_content_type_middleware.py b/tests/web/test_content_type_middleware.py new file mode 100644 index 00000000..103bd615 --- /dev/null +++ b/tests/web/test_content_type_middleware.py @@ -0,0 +1,40 @@ +from unittest.mock import Mock + +OUTPUTS_ENDPOINT = '/api/v1/outputs/' + + +def test_middleware_does_nothing_when_no_content_type_is_provided(): + from bigchaindb.web.strip_content_type_middleware import StripContentTypeMiddleware + mock = Mock() + middleware = StripContentTypeMiddleware(mock) + middleware({'REQUEST_METHOD': 'GET'}, None) + + assert 'CONTENT_TYPE' not in mock.call_args[0][0] + + +def test_middleware_strips_content_type_from_gets(): + from bigchaindb.web.strip_content_type_middleware import StripContentTypeMiddleware + mock = Mock() + middleware = StripContentTypeMiddleware(mock) + middleware({'REQUEST_METHOD': 'GET', + 'CONTENT_TYPE': 'application/json'}, + None) + + assert 'CONTENT_TYPE' not in mock.call_args[0][0] + + +def test_middleware_does_notstrip_content_type_from_other_methods(): + from bigchaindb.web.strip_content_type_middleware import StripContentTypeMiddleware + mock = Mock() + middleware = StripContentTypeMiddleware(mock) + middleware({'REQUEST_METHOD': 'POST', + 'CONTENT_TYPE': 'application/json'}, + None) + + assert 'CONTENT_TYPE' in mock.call_args[0][0] + + +def test_get_outputs_endpoint_with_content_type(client, user_pk): + res = client.get(OUTPUTS_ENDPOINT + '?public_key={}'.format(user_pk), + headers=[('Content-Type', 'application/json')]) + assert res.status_code == 200