20
22
from .exceptions import LocationParseError
25
class Url(namedtuple('Url', ['scheme', 'auth', 'host', 'port', 'path', 'query', 'fragment'])):
27
Datastructure for representing an HTTP URL. Used as a return value for
32
def __new__(cls, scheme=None, auth=None, host=None, port=None, path=None, query=None, fragment=None):
33
return super(Url, cls).__new__(cls, scheme, auth, host, port, path, query, fragment)
37
"""For backwards-compatibility with urlparse. We're nice like that."""
41
def request_uri(self):
42
"""Absolute path including the query string."""
43
uri = self.path or '/'
45
if self.query is not None:
46
uri += '?' + self.query
51
def split_first(s, delims):
53
Given a string and an iterable of delimiters, split on the first found
54
delimiter. Return two split parts and the matched delimiter.
56
If not found, then the first part is the full input string.
60
>>> split_first('foo/bar?baz', '?/=')
61
('foo', 'bar?baz', '/')
62
>>> split_first('foo/bar?baz', '123')
63
('foo/bar?baz', '', None)
65
Scales linearly with number of delims. Not ideal for large number of delims.
74
if min_idx is None or idx < min_idx:
78
if min_idx is None or min_idx < 0:
81
return s[:min_idx], s[min_idx+1:], min_delim
86
Given a url, return a parsed :class:`.Url` namedtuple. Best-effort is
87
performed to parse incomplete urls. Fields not provided will be None.
89
Partly backwards-compatible with :mod:`urlparse`.
93
>>> parse_url('http://google.com/mail/')
94
Url(scheme='http', host='google.com', port=None, path='/', ...)
95
>>> prase_url('google.com:80')
96
Url(scheme=None, host='google.com', port=80, path=None, ...)
97
>>> prase_url('/foo?bar')
98
Url(scheme=None, host=None, port=None, path='/foo', query='bar', ...)
101
# While this code has overlap with stdlib's urlparse, it is much
102
# simplified for our needs and less annoying.
103
# Additionally, this imeplementations does silly things to be optimal
116
scheme, url = url.split('://', 1)
118
# Find the earliest Authority Terminator
119
# (http://tools.ietf.org/html/rfc3986#section-3.2)
120
url, path_, delim = split_first(url, ['/', '?', '#'])
123
# Reassemble the path
128
auth, url = url.split('@', 1)
131
if url and url[0] == '[':
132
host, url = url[1:].split(']', 1)
136
_host, port = url.split(':', 1)
141
if not port.isdigit():
142
raise LocationParseError("Failed to parse: %s" % url)
146
elif not host and url:
150
return Url(scheme, auth, host, port, path, query, fragment)
154
path, fragment = path.split('#', 1)
158
path, query = path.split('?', 1)
160
return Url(scheme, auth, host, port, path, query, fragment)
165
Deprecated. Use :func:`.parse_url` instead.
168
return p.scheme or 'http', p.hostname, p.port
23
171
def make_headers(keep_alive=None, accept_encoding=None, user_agent=None,
77
Given a url, return its scheme, host and port (None if it's not there).
81
>>> get_host('http://google.com/mail/')
82
('http', 'google.com', None)
83
>>> get_host('google.com:80')
84
('http', 'google.com', 80)
87
# This code is actually similar to urlparse.urlsplit, but much
88
# simplified for our needs.
93
scheme, url = url.split('://', 1)
95
url, _path = url.split('/', 1)
97
_auth, url = url.split('@', 1)
99
url, port = url.split(':', 1)
101
if not port.isdigit():
102
raise LocationParseError("Failed to parse: %s" % url)
106
return scheme, url, port
110
223
def is_connection_dropped(conn):
112
225
Returns True if the connection is dropped and should be closed.
115
``HTTPConnection`` object.
228
:class:`httplib.HTTPConnection` object.
117
230
Note: For platforms like AppEngine, this will always return ``False`` to
118
231
let the platform handle connection recycling transparently for us.
120
233
sock = getattr(conn, 'sock', False)
121
if not sock: #Platform-specific: AppEngine
234
if not sock: # Platform-specific: AppEngine
124
237
if not poll: # Platform-specific
125
if not select: #Platform-specific: AppEngine
238
if not select: # Platform-specific: AppEngine
128
return select([sock], [], [], 0.0)[0]
242
return select([sock], [], [], 0.0)[0]
130
246
# This version is better on platforms that support it.