Handle content-type header charset value for streaming API
[twitter-api-cdsw] / oauthlib / oauth1 / rfc5849 / parameters.py
1 # -*- coding: utf-8 -*-
2 """
3 oauthlib.parameters
4 ~~~~~~~~~~~~~~~~~~~
5
6 This module contains methods related to `section 3.5`_ of the OAuth 1.0a spec.
7
8 .. _`section 3.5`: http://tools.ietf.org/html/rfc5849#section-3.5
9 """
10 from __future__ import absolute_import, unicode_literals
11
12 try:
13     from urlparse import urlparse, urlunparse
14 except ImportError:
15     from urllib.parse import urlparse, urlunparse
16 from . import utils
17 from oauthlib.common import extract_params, urlencode
18
19
20 # TODO: do we need filter_params now that oauth_params are handled by Request?
21 #       We can easily pass in just oauth protocol params.
22 @utils.filter_params
23 def prepare_headers(oauth_params, headers=None, realm=None):
24     """**Prepare the Authorization header.**
25     Per `section 3.5.1`_ of the spec.
26
27     Protocol parameters can be transmitted using the HTTP "Authorization"
28     header field as defined by `RFC2617`_ with the auth-scheme name set to
29     "OAuth" (case insensitive).
30
31     For example::
32
33         Authorization: OAuth realm="Example",
34             oauth_consumer_key="0685bd9184jfhq22",
35             oauth_token="ad180jjd733klru7",
36             oauth_signature_method="HMAC-SHA1",
37             oauth_signature="wOJIO9A2W5mFwDgiDvZbTSMK%2FPY%3D",
38             oauth_timestamp="137131200",
39             oauth_nonce="4572616e48616d6d65724c61686176",
40             oauth_version="1.0"
41
42
43     .. _`section 3.5.1`: http://tools.ietf.org/html/rfc5849#section-3.5.1
44     .. _`RFC2617`: http://tools.ietf.org/html/rfc2617
45     """
46     headers = headers or {}
47
48     # Protocol parameters SHALL be included in the "Authorization" header
49     # field as follows:
50     authorization_header_parameters_parts = []
51     for oauth_parameter_name, value in oauth_params:
52         # 1.  Parameter names and values are encoded per Parameter Encoding
53         #     (`Section 3.6`_)
54         #
55         # .. _`Section 3.6`: http://tools.ietf.org/html/rfc5849#section-3.6
56         escaped_name = utils.escape(oauth_parameter_name)
57         escaped_value = utils.escape(value)
58
59         # 2.  Each parameter's name is immediately followed by an "=" character
60         #     (ASCII code 61), a """ character (ASCII code 34), the parameter
61         #     value (MAY be empty), and another """ character (ASCII code 34).
62         part = '{0}="{1}"'.format(escaped_name, escaped_value)
63
64         authorization_header_parameters_parts.append(part)
65
66     # 3.  Parameters are separated by a "," character (ASCII code 44) and
67     #     OPTIONAL linear whitespace per `RFC2617`_.
68     #
69     # .. _`RFC2617`: http://tools.ietf.org/html/rfc2617
70     authorization_header_parameters = ', '.join(
71         authorization_header_parameters_parts)
72
73     # 4.  The OPTIONAL "realm" parameter MAY be added and interpreted per
74     #     `RFC2617 section 1.2`_.
75     #
76     # .. _`RFC2617 section 1.2`: http://tools.ietf.org/html/rfc2617#section-1.2
77     if realm:
78         # NOTE: realm should *not* be escaped
79         authorization_header_parameters = ('realm="%s", ' % realm +
80                                            authorization_header_parameters)
81
82     # the auth-scheme name set to "OAuth" (case insensitive).
83     authorization_header = 'OAuth %s' % authorization_header_parameters
84
85     # contribute the Authorization header to the given headers
86     full_headers = {}
87     full_headers.update(headers)
88     full_headers['Authorization'] = authorization_header
89     return full_headers
90
91
92 def _append_params(oauth_params, params):
93     """Append OAuth params to an existing set of parameters.
94
95     Both params and oauth_params is must be lists of 2-tuples.
96
97     Per `section 3.5.2`_ and `3.5.3`_ of the spec.
98
99     .. _`section 3.5.2`: http://tools.ietf.org/html/rfc5849#section-3.5.2
100     .. _`3.5.3`: http://tools.ietf.org/html/rfc5849#section-3.5.3
101
102     """
103     merged = list(params)
104     merged.extend(oauth_params)
105     # The request URI / entity-body MAY include other request-specific
106     # parameters, in which case, the protocol parameters SHOULD be appended
107     # following the request-specific parameters, properly separated by an "&"
108     # character (ASCII code 38)
109     merged.sort(key=lambda i: i[0].startswith('oauth_'))
110     return merged
111
112
113 def prepare_form_encoded_body(oauth_params, body):
114     """Prepare the Form-Encoded Body.
115
116     Per `section 3.5.2`_ of the spec.
117
118     .. _`section 3.5.2`: http://tools.ietf.org/html/rfc5849#section-3.5.2
119
120     """
121     # append OAuth params to the existing body
122     return _append_params(oauth_params, body)
123
124
125 def prepare_request_uri_query(oauth_params, uri):
126     """Prepare the Request URI Query.
127
128     Per `section 3.5.3`_ of the spec.
129
130     .. _`section 3.5.3`: http://tools.ietf.org/html/rfc5849#section-3.5.3
131
132     """
133     # append OAuth params to the existing set of query components
134     sch, net, path, par, query, fra = urlparse(uri)
135     query = urlencode(
136         _append_params(oauth_params, extract_params(query) or []))
137     return urlunparse((sch, net, path, par, query, fra))

Benjamin Mako Hill || Want to submit a patch?