Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix spaces encoding in parameters #88

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
35 changes: 35 additions & 0 deletions requests_oauthlib/oauth1_session.py
Expand Up @@ -7,6 +7,8 @@

from oauthlib.common import add_params_to_uri, urldecode
from oauthlib.oauth1 import SIGNATURE_HMAC, SIGNATURE_TYPE_AUTH_HEADER
from requests.utils import to_key_val_list
from urllib import urlencode
import requests

from . import OAuth1
Expand Down Expand Up @@ -264,3 +266,36 @@ def _fetch_token(self, url):
token = dict(urldecode(self.post(url).text))
self._populate_attributes(token)
return token

def _urlencode_for_oauth(self, params):
"""
This method does exactly what requests.models.RequestEncodingMixin._encode_params() does,
with one subtle but important difference: instead of replacing spaces by +, they are
replaced by %20, which is needed for OAuth.

See: http://troy.yort.com/2-common-problems-with-oauth-client-libraries/
"""
if isinstance(params, (str, bytes)):
return params
elif hasattr(params, 'read'):
return params
elif hasattr(params, '__iter__'):
result = []
for k, vs in to_key_val_list(params):
if isinstance(vs, basestring) or not hasattr(vs, '__iter__'):
vs = [vs]
for v in vs:
if v is not None:
result.append(
(
k.encode('utf-8') if isinstance(k, str) else k,
v.encode('utf-8') if isinstance(v, str) else v,
)
)
return urlencode(result, doseq=True).replace('+', '%20')
else:
return params

def request(self, method, url, params=None, *args, **kwargs):
params = self._urlencode_for_oauth(params)
return super(OAuth1Session, self).request(method, url, params, *args, **kwargs)
9 changes: 9 additions & 0 deletions tests/test_oauth1_session.py
Expand Up @@ -158,6 +158,15 @@ def test_fetch_access_token(self):
self.assertTrue(isinstance(k, unicode_type))
self.assertTrue(isinstance(v, unicode_type))

def test_params_with_spaces(self):
class RequestIntercepter(OAuth1Session):
def send(self, request, **kwargs):
self.sent_url = request.url

auth = RequestIntercepter('foo')
auth.get('http://example.com/', params={'q': 'foo bar'})
self.assertEqual(str('http://example.com/?q=foo%20bar'), auth.sent_url)

def verify_signature(self, signature):
def fake_send(r, **kwargs):
auth_header = r.headers['Authorization']
Expand Down