summaryrefslogtreecommitdiff
path: root/oauthlib/oauth1/rfc5849/parameters.py
blob: c809a390e101e1e521cc780a24408d1641473adc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# -*- coding: utf-8 -*-
from __future__ import absolute_import

"""
oauthlib.parameters
~~~~~~~~~~~~~~~~~~~

This module contains methods related to `section 3.5`_ of the OAuth 1.0a spec.

.. _`section 3.5`: http://tools.ietf.org/html/rfc5849#section-3.5
"""

from urlparse import urlparse, urlunparse, parse_qsl
from . import utils


def order_params(target):
    """Decorator which reorders params contents to start with oauth_* params

    Assumes the decorated method takes a params dict or list of tuples as its
    first argument.
    """
    def wrapper(params, *args, **kwargs):
        ordered_params = order_oauth_parameters(params)
        return target(ordered_params, *args, **kwargs)

    wrapper.__doc__ = target.__doc__
    return wrapper


def order_oauth_parameters(params):
    """Order a parameters dict or list of tuples with OAuth ones first

    Per `section 3.5`_ of the spec.

    .. _`section 3.5`: http://tools.ietf.org/html/rfc5849#section-3.5
    """
    # Convert dictionaries to list of tuples
    if isinstance(params, dict):
        params = params.items()

    ordered = []
    for k, v in params:
        if k.startswith("oauth_"):
            ordered.insert(0, (k, v))
        else:
            ordered.append((k, v))

    return ordered


@utils.filter_params
def prepare_headers(params, headers, realm=None):
    """Prepare the Authorization header.

    Per `section 3.5.1`_ of the spec.

    .. _`section 3.5.1`: http://tools.ietf.org/html/rfc5849#section-3.5.1

    """
    headers = headers or {}

    # TODO: Realm should always be the first parameter, right?
    # Doesn't seem to be specified.
    full_params = []
    if realm:
        full_params.append((u"realm", realm))
    full_params.extend(params)

    # Only oauth_ and realm parameters should remain by this point.
    authorization_header = 'OAuth ' + ', '.join(
        ['{0}="{1}"'.format(utils.escape(k), utils.escape(v)) for k, v in full_params])

    # contribute the Authorization header to the given headers
    full_headers = {}
    full_headers.update(headers)
    full_headers['Authorization'] = authorization_header
    return full_headers


def _add_params_to_qs(query, params):
    queryparams = parse_qsl(query, True)
    queryparams.extend(params)
    queryparams.sort(key=lambda i: i[0].startswith('oauth_'))
    return utils.urlencode(queryparams)


@order_params
def prepare_form_encoded_body(params, body):
    """Prepare the Form-Encoded Body.

    Per `section 3.5.2`_ of the spec.

    params: OAuth parameters and data (i.e. POST data).

    .. _`section 3.5.2`: http://tools.ietf.org/html/rfc5849#section-3.5.2

    """
    # append OAuth params to the existing body
    return _add_params_to_qs(body, params)


@order_params
def prepare_request_uri_query(params, uri):
    """Prepare the Request URI Query.

    Per `section 3.5.3`_ of the spec.

    params: OAuth parameters and data (i.e. POST data).
    url: The request url. Query components will be removed.

    .. _`section 3.5.3`: http://tools.ietf.org/html/rfc5849#section-3.5.3

    """
    # append OAuth params to the existing set of query components
    sch, net, path, par, query, fra = urlparse(uri)
    query = _add_params_to_qs(query, params)
    return urlunparse((sch, net, path, par, query, fra))