From 2fdc14a2424d7687358598441db8bcfd8fe9eb69 Mon Sep 17 00:00:00 2001 From: Ben Sturmfels Date: Tue, 19 Jan 2016 23:53:52 +1100 Subject: [PATCH] trac#5397: Allow decode_request to parse content-type headers with extra options. It previously parsed "Content-Type: application/x-www-form-urlencoded", but not "Content-Type: application/x-www-form-urlencoded; charset=utf-8". --- mediagoblin/tests/test_tools.py | 61 +++++++++++++++++++++++++++++++++ mediagoblin/tools/request.py | 7 ++-- 2 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 mediagoblin/tests/test_tools.py diff --git a/mediagoblin/tests/test_tools.py b/mediagoblin/tests/test_tools.py new file mode 100644 index 00000000..6d3dd475 --- /dev/null +++ b/mediagoblin/tests/test_tools.py @@ -0,0 +1,61 @@ +# GNU MediaGoblin -- federated, autonomous media hosting +# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +from __future__ import absolute_import, unicode_literals + +from werkzeug.wrappers import Request +from werkzeug.test import EnvironBuilder + +from mediagoblin.tools.request import decode_request + +class TestDecodeRequest(object): + """Test the decode_request function.""" + + def test_form_type(self): + """Try a normal form-urlencoded request.""" + builder = EnvironBuilder(method='POST', data={'foo': 'bar'}) + request = Request(builder.get_environ()) + data = decode_request(request) + assert data['foo'] == 'bar' + + def test_json_type(self): + """Try a normal JSON request.""" + builder = EnvironBuilder( + method='POST', content_type='application/json', + data='{"foo": "bar"}') + request = Request(builder.get_environ()) + data = decode_request(request) + assert data['foo'] == 'bar' + + def test_content_type_with_options(self): + """Content-Type can also have options.""" + builder = EnvironBuilder( + method='POST', + content_type='application/x-www-form-urlencoded; charset=utf-8') + request = Request(builder.get_environ()) + # Must populate form field manually with non-default content-type. + request.form = {'foo': 'bar'} + data = decode_request(request) + assert data['foo'] == 'bar' + + def test_form_type_is_default(self): + """Assume form-urlencoded if blank in the request.""" + builder = EnvironBuilder(method='POST', content_type='') + request = Request(builder.get_environ()) + # Must populate form field manually with non-default content-type. + request.form = {'foo': 'bar'} + data = decode_request(request) + assert data['foo'] == 'bar' diff --git a/mediagoblin/tools/request.py b/mediagoblin/tools/request.py index d2cb0f6a..af06967b 100644 --- a/mediagoblin/tools/request.py +++ b/mediagoblin/tools/request.py @@ -17,6 +17,8 @@ import json import logging +from werkzeug.http import parse_options_header + from mediagoblin.db.models import User, AccessToken from mediagoblin.oauth.tools.request import decode_authorization_header @@ -60,10 +62,11 @@ def setup_user_in_request(request): def decode_request(request): """ Decodes a request based on MIME-Type """ data = request.data + content_type, _ = parse_options_header(request.content_type) - if request.content_type == json_encoded: + if content_type == json_encoded: data = json.loads(data) - elif request.content_type == form_encoded or request.content_type == "": + elif content_type == form_encoded or content_type == "": data = request.form else: data = "" -- 2.25.1