1 # -*- coding: utf-8 -*-
2 from __future__ import unicode_literals
6 from oauthlib.common import extract_params
7 from oauthlib.oauth1 import Client, SIGNATURE_HMAC, SIGNATURE_TYPE_AUTH_HEADER
8 from oauthlib.oauth1 import SIGNATURE_TYPE_BODY
9 from requests.compat import is_py3
10 from requests.utils import to_native_string
12 CONTENT_TYPE_FORM_URLENCODED = 'application/x-www-form-urlencoded'
13 CONTENT_TYPE_MULTI_PART = 'multipart/form-data'
18 log = logging.getLogger(__name__)
20 # OBS!: Correct signing of requests are conditional on invoking OAuth1
21 # as the last step of preparing a request, or at least having the
22 # content-type set properly.
24 """Signs the request using OAuth 1 (RFC5849)"""
28 def __init__(self, client_key,
30 resource_owner_key=None,
31 resource_owner_secret=None,
33 signature_method=SIGNATURE_HMAC,
34 signature_type=SIGNATURE_TYPE_AUTH_HEADER,
35 rsa_key=None, verifier=None,
38 force_include_body=False,
42 signature_type = signature_type.upper()
43 except AttributeError:
46 client_class = client_class or self.client_class
48 self.force_include_body = force_include_body
50 self.client = client_class(client_key, client_secret, resource_owner_key,
51 resource_owner_secret, callback_uri, signature_method,
52 signature_type, rsa_key, verifier, decoding=decoding, **kwargs)
54 def __call__(self, r):
55 """Add OAuth parameters to the request.
57 Parameters may be included from the body if the content-type is
58 urlencoded, if no content type is set a guess is made.
60 # Overwriting url is safe here as request will not modify it past
62 log.debug('Signing request %s using client %s', r, self.client)
64 content_type = r.headers.get('Content-Type', '')
65 if (not content_type and extract_params(r.body)
66 or self.client.signature_type == SIGNATURE_TYPE_BODY):
67 content_type = CONTENT_TYPE_FORM_URLENCODED
68 if not isinstance(content_type, unicode):
69 content_type = content_type.decode('utf-8')
71 is_form_encoded = (CONTENT_TYPE_FORM_URLENCODED in content_type)
73 log.debug('Including body in call to sign: %s',
74 is_form_encoded or self.force_include_body)
77 r.headers['Content-Type'] = CONTENT_TYPE_FORM_URLENCODED
78 r.url, headers, r.body = self.client.sign(
79 unicode(r.url), unicode(r.method), r.body or '', r.headers)
80 elif self.force_include_body:
81 # To allow custom clients to work on non form encoded bodies.
82 r.url, headers, r.body = self.client.sign(
83 unicode(r.url), unicode(r.method), r.body or '', r.headers)
85 # Omit body data in the signing of non form-encoded requests
86 r.url, headers, _ = self.client.sign(
87 unicode(r.url), unicode(r.method), None, r.headers)
89 r.prepare_headers(headers)
90 r.url = to_native_string(r.url)
91 log.debug('Updated url: %s', r.url)
92 log.debug('Updated headers: %s', headers)
93 log.debug('Updated body: %r', r.body)