~fginther/vmbuilder/new-artful-builder

« back to all changes in this revision

Viewing changes to pylib/requests/packages/urllib3/request.py

  • Committer: Ben Howard
  • Date: 2014-08-19 20:30:00 UTC
  • Revision ID: ben.howard@ubuntu.com-20140819203000-9gfgaryo1w41orxu
12.04 does not ship with a version of python3-requests, so we need
to provided it.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# urllib3/request.py
 
2
# Copyright 2008-2013 Andrey Petrov and contributors (see CONTRIBUTORS.txt)
 
3
#
 
4
# This module is part of urllib3 and is released under
 
5
# the MIT License: http://www.opensource.org/licenses/mit-license.php
 
6
 
 
7
try:
 
8
    from urllib.parse import urlencode
 
9
except ImportError:
 
10
    from urllib import urlencode
 
11
 
 
12
from .filepost import encode_multipart_formdata
 
13
 
 
14
 
 
15
__all__ = ['RequestMethods']
 
16
 
 
17
 
 
18
class RequestMethods(object):
 
19
    """
 
20
    Convenience mixin for classes who implement a :meth:`urlopen` method, such
 
21
    as :class:`~urllib3.connectionpool.HTTPConnectionPool` and
 
22
    :class:`~urllib3.poolmanager.PoolManager`.
 
23
 
 
24
    Provides behavior for making common types of HTTP request methods and
 
25
    decides which type of request field encoding to use.
 
26
 
 
27
    Specifically,
 
28
 
 
29
    :meth:`.request_encode_url` is for sending requests whose fields are encoded
 
30
    in the URL (such as GET, HEAD, DELETE).
 
31
 
 
32
    :meth:`.request_encode_body` is for sending requests whose fields are
 
33
    encoded in the *body* of the request using multipart or www-form-urlencoded
 
34
    (such as for POST, PUT, PATCH).
 
35
 
 
36
    :meth:`.request` is for making any kind of request, it will look up the
 
37
    appropriate encoding format and use one of the above two methods to make
 
38
    the request.
 
39
 
 
40
    Initializer parameters:
 
41
 
 
42
    :param headers:
 
43
        Headers to include with all requests, unless other headers are given
 
44
        explicitly.
 
45
    """
 
46
 
 
47
    _encode_url_methods = set(['DELETE', 'GET', 'HEAD', 'OPTIONS'])
 
48
 
 
49
    def __init__(self, headers=None):
 
50
        self.headers = headers or {}
 
51
 
 
52
    def urlopen(self, method, url, body=None, headers=None,
 
53
                encode_multipart=True, multipart_boundary=None,
 
54
                **kw): # Abstract
 
55
        raise NotImplemented("Classes extending RequestMethods must implement "
 
56
                             "their own ``urlopen`` method.")
 
57
 
 
58
    def request(self, method, url, fields=None, headers=None, **urlopen_kw):
 
59
        """
 
60
        Make a request using :meth:`urlopen` with the appropriate encoding of
 
61
        ``fields`` based on the ``method`` used.
 
62
 
 
63
        This is a convenience method that requires the least amount of manual
 
64
        effort. It can be used in most situations, while still having the option
 
65
        to drop down to more specific methods when necessary, such as
 
66
        :meth:`request_encode_url`, :meth:`request_encode_body`,
 
67
        or even the lowest level :meth:`urlopen`.
 
68
        """
 
69
        method = method.upper()
 
70
 
 
71
        if method in self._encode_url_methods:
 
72
            return self.request_encode_url(method, url, fields=fields,
 
73
                                            headers=headers,
 
74
                                            **urlopen_kw)
 
75
        else:
 
76
            return self.request_encode_body(method, url, fields=fields,
 
77
                                             headers=headers,
 
78
                                             **urlopen_kw)
 
79
 
 
80
    def request_encode_url(self, method, url, fields=None, **urlopen_kw):
 
81
        """
 
82
        Make a request using :meth:`urlopen` with the ``fields`` encoded in
 
83
        the url. This is useful for request methods like GET, HEAD, DELETE, etc.
 
84
        """
 
85
        if fields:
 
86
            url += '?' + urlencode(fields)
 
87
        return self.urlopen(method, url, **urlopen_kw)
 
88
 
 
89
    def request_encode_body(self, method, url, fields=None, headers=None,
 
90
                            encode_multipart=True, multipart_boundary=None,
 
91
                            **urlopen_kw):
 
92
        """
 
93
        Make a request using :meth:`urlopen` with the ``fields`` encoded in
 
94
        the body. This is useful for request methods like POST, PUT, PATCH, etc.
 
95
 
 
96
        When ``encode_multipart=True`` (default), then
 
97
        :meth:`urllib3.filepost.encode_multipart_formdata` is used to encode the
 
98
        payload with the appropriate content type. Otherwise
 
99
        :meth:`urllib.urlencode` is used with the
 
100
        'application/x-www-form-urlencoded' content type.
 
101
 
 
102
        Multipart encoding must be used when posting files, and it's reasonably
 
103
        safe to use it in other times too. However, it may break request signing,
 
104
        such as with OAuth.
 
105
 
 
106
        Supports an optional ``fields`` parameter of key/value strings AND
 
107
        key/filetuple. A filetuple is a (filename, data, MIME type) tuple where
 
108
        the MIME type is optional. For example: ::
 
109
 
 
110
            fields = {
 
111
                'foo': 'bar',
 
112
                'fakefile': ('foofile.txt', 'contents of foofile'),
 
113
                'realfile': ('barfile.txt', open('realfile').read()),
 
114
                'typedfile': ('bazfile.bin', open('bazfile').read(),
 
115
                              'image/jpeg'),
 
116
                'nonamefile': 'contents of nonamefile field',
 
117
            }
 
118
 
 
119
        When uploading a file, providing a filename (the first parameter of the
 
120
        tuple) is optional but recommended to best mimick behavior of browsers.
 
121
 
 
122
        Note that if ``headers`` are supplied, the 'Content-Type' header will be
 
123
        overwritten because it depends on the dynamic random boundary string
 
124
        which is used to compose the body of the request. The random boundary
 
125
        string can be explicitly set with the ``multipart_boundary`` parameter.
 
126
        """
 
127
        if encode_multipart:
 
128
            body, content_type = encode_multipart_formdata(fields or {},
 
129
                                    boundary=multipart_boundary)
 
130
        else:
 
131
            body, content_type = (urlencode(fields or {}),
 
132
                                    'application/x-www-form-urlencoded')
 
133
 
 
134
        if headers is None:
 
135
            headers = self.headers
 
136
 
 
137
        headers_ = {'Content-Type': content_type}
 
138
        headers_.update(headers)
 
139
 
 
140
        return self.urlopen(method, url, body=body, headers=headers_,
 
141
                            **urlopen_kw)