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