1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 from __future__ import absolute_import
21
22 import socket
23 from ._compat import urlparse, urlunparse, quote, unquote
24
25
26 -class Url(object):
27 """
28 Simple URL parser/constructor, handles URLs of the form:
29
30 <scheme>://<user>:<password>@<host>:<port>/<path>
31
32 All components can be None if not specified in the URL string.
33
34 The port can be specified as a service name, e.g. 'amqp' in the
35 URL string but Url.port always gives the integer value.
36
37 Warning: The placement of user and password in URLs is not
38 recommended. It can result in credentials leaking out in program
39 logs. Use connection configuration attributes instead.
40
41 @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
42 @ivar user: Username
43 @ivar password: Password
44 @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
45 @ivar port: Integer port.
46 @ivar host_port: Returns host:port
47 """
48
49 AMQPS = "amqps"
50 AMQP = "amqp"
51
53 """An integer port number that can be constructed from a service name string"""
54
56 """@param value: integer port number or string service name."""
57 port = super(Url.Port, cls).__new__(cls, cls._port_int(value))
58 setattr(port, 'name', str(value))
59 return port
60
62 return str(self) == x or int(self) == x
63
66
69
70 @staticmethod
72 """Convert service, an integer or a service name, into an integer port number."""
73 try:
74 return int(value)
75 except ValueError:
76 try:
77 return socket.getservbyname(value)
78 except socket.error:
79
80 if value == Url.AMQPS:
81 return 5671
82 elif value == Url.AMQP:
83 return 5672
84 else:
85 raise ValueError("Not a valid port number or service name: '%s'" % value)
86
87 - def __init__(self, url=None, defaults=True, **kwargs):
88 """
89 @param url: URL string to parse.
90 @param defaults: If true, fill in missing default values in the URL.
91 If false, you can fill them in later by calling self.defaults()
92 @param kwargs: scheme, user, password, host, port, path.
93 If specified, replaces corresponding part in url string.
94 """
95 if isinstance(url, Url):
96 self.scheme = url.scheme
97 self.username = url.username
98 self.password = url.password
99 self.host = url.host
100 self._port = url._port
101 self._path = url._path
102 self._params = url._params
103 self._query = url._query
104 self._fragment = url._fragment
105 elif url:
106 if not url.startswith('//'):
107 p = url.partition(':')
108 if '/' in p[0] or not p[2].startswith('//'):
109 url = '//' + url
110 u = urlparse(url)
111 if not u: raise ValueError("Invalid URL '%s'" % url)
112 self.scheme = None if not u.scheme else u.scheme
113 self.username = u.username and unquote(u.username)
114 self.password = u.password and unquote(u.password)
115 self.host = None if not u.hostname else u.hostname
116 self._port = self._parse_port(u.netloc)
117 self._path = None if not u.path else u.path
118 self._params = u.params
119 self._query = u.query
120 self._fragment = u.fragment
121 else:
122 self.scheme = None
123 self.username = None
124 self.password = None
125 self.host = None
126 self._port = None
127 self._path = None
128 self._params = None
129 self._query = None
130 self._fragment = None
131 for k in kwargs:
132 getattr(self, k)
133 setattr(self, k, kwargs[k])
134 if defaults: self.defaults()
135
136 @staticmethod
138 netloc = nl.split('@')[-1].split(']')[-1]
139 if ':' in netloc:
140 port = netloc.split(':')[1]
141 if port:
142 return port
143 return None
144
145 @property
147 return self._path if not self._path or self._path[0] != '/' else self._path[1:]
148
149 @path.setter
151 self._path = p if p[0] == '/' else '/' + p
152
153 @property
155 return self._port and Url.Port(self._port)
156
157 @port.setter
160
161 @property
163 hostport = ''
164 if self.host:
165 hostport = self.host
166 if self._port:
167 hostport += ':'
168 hostport += str(self._port)
169 userpart = ''
170 if self.username:
171 userpart += quote(self.username)
172 if self.password:
173 userpart += ':'
174 userpart += quote(self.password)
175 if self.username or self.password:
176 userpart += '@'
177 return userpart + hostport
178
180 if self.scheme \
181 and not self._netloc and not self._path \
182 and not self._params and not self._query and not self._fragment:
183 return self.scheme + '://'
184 return urlunparse((self.scheme or '', self._netloc or '', self._path or '',
185 self._params or '', self._query or '', self._fragment or ''))
186
188 return "Url('%s')" % self
189
191 return str(self) == str(x)
192
195
197 """
198 Fill in missing values (scheme, host or port) with defaults
199 @return: self
200 """
201 self.scheme = self.scheme or self.AMQP
202 self.host = self.host or '0.0.0.0'
203 self._port = self._port or self.Port(self.scheme)
204 return self
205