diff --git a/.travis.yml b/.travis.yml index a20f7099..7393b5b1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ python: - "2.7" - "3.3" - "3.4" + - "3.5" install: - pip install -r requirements.txt - pip install codecov pytest-cov diff --git a/oauth2/__init__.py b/oauth2/__init__.py index a1776a75..fc49e105 100644 --- a/oauth2/__init__.py +++ b/oauth2/__init__.py @@ -468,12 +468,20 @@ def get_normalized_parameters(self): # Include any query string parameters from the provided URL query = urlparse(self.url)[4] - url_items = self._split_url_string(query).items() url_items = [(to_utf8(k), to_utf8_optional_iterator(v)) for k, v in url_items if k != 'oauth_signature' ] - items.extend(url_items) + + # Merge together URL and POST parameters. + # Eliminates parameters duplicated between URL and POST. + items_dict = {} + for k, v in items: + items_dict.setdefault(k, []).append(v) + for k, v in url_items: + if not (k in items_dict and v in items_dict[k]): + items.append((k, v)) items.sort() + encoded_str = urlencode(items, True) # Encode signature parameters per Oauth Core 1.0 protocol # spec draft 7, section 3.6 diff --git a/tests/test_oauth.py b/tests/test_oauth.py index 58854564..7b272e24 100644 --- a/tests/test_oauth.py +++ b/tests/test_oauth.py @@ -744,6 +744,39 @@ def test_get_normalized_parameters_duplicate(self): self.assertEqual(expected, res) + def test_get_normalized_parameters_duplicate_url_and_post_parameters(self): + url = ("http://example.com/v2/search/videos" + '?oauth_nonce=79815175' + '&oauth_timestamp=1295397962' + '&oauth_consumer_key=mykey' + '&oauth_signature_method=HMAC-SHA1' + '&tag=one' + '&search=duplicate' + '&offset=10' + '&oauth_version=1.0' + '&oauth_signature=spWLI%2FGQjid7sQVd5%2FarahRxzJg%3D') + + # duplicates the "search" query parameter + parameters = { + "tag": "two", + "search": "duplicate", + } + req = oauth.Request("POST", url, parameters) + + res = req.get_normalized_parameters() + + expected = ('oauth_consumer_key=mykey' + '&oauth_nonce=79815175' + '&oauth_signature_method=HMAC-SHA1' + '&oauth_timestamp=1295397962' + '&oauth_version=1.0' + '&offset=10' + '&search=duplicate' + '&tag=one' + '&tag=two') + + self.assertEqual(expected, res) + def test_get_normalized_parameters_multiple(self): url = "http://example.com/v2/search/videos?oauth_nonce=79815175&oauth_timestamp=1295397962&oauth_consumer_key=mykey&oauth_signature_method=HMAC-SHA1&oauth_version=1.0&offset=10&oauth_signature=spWLI%2FGQjid7sQVd5%2FarahRxzJg%3D&tag=one&tag=two"