The API client MAASClient doesn't encode list parameters when doing a GET
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
MAAS |
Fix Released
|
Medium
|
Newell Jensen |
Bug Description
The code in maas_client.py assumes that all the parameters are strings and so fails with the stack trace below.
It would be more useful if it takes list params and encodes them appropriately. For example, if passed
client.get(url, op="thing", param=["foo", "bar", "baz"])
it should enode like this:
param=foo&
In [9]: r=client.get(url, op="list", mac_address=
-------
AttributeError Traceback (most recent call last)
<ipython-
----> 1 r=client.get(url, op="list", mac_address=
/home/ed/
215 if op is not None:
216 kwargs['op'] = op
--> 217 url, headers = self._formulate
218 return self.dispatcher
219 url, method="GET", headers=headers)
/home/ed/
176 url = self._make_
177 if params is not None and len(params) > 0:
--> 178 url += "?" + urlencode(
179 headers = {}
180 self.auth.
/home/ed/
46 return b"&".join(
47 b"%s=%s" % (enc(name), enc(value))
---> 48 for name, value in data)
/home/ed/
46 return b"&".join(
47 b"%s=%s" % (enc(name), enc(value))
---> 48 for name, value in data)
/home/ed/
43 """
44 enc = lambda string: quote_plus(
---> 45 string.
46 return b"&".join(
47 b"%s=%s" % (enc(name), enc(value))
/usr/lib/
1293 s = quote(s, safe + ' ')
1294 return s.replace(' ', '+')
-> 1295 return quote(s, safe)
1296
1297 def urlencode(query, doseq=0):
/usr/lib/
1284 safe = always_safe + safe
1285 _safe_quoters[
-> 1286 if not s.rstrip(safe):
1287 return s
1288 return ''.join(map(quoter, s))
AttributeError: 'list' object has no attribute 'rstrip'
Related branches
- Julian Edwards (community): Approve
-
Diff: 78 lines (+42/-1)2 files modifiedsrc/apiclient/maas_client.py (+17/-1)
src/apiclient/tests/test_maas_client.py (+25/-0)
Changed in maas: | |
status: | New → Triaged |
importance: | Undecided → Medium |
tags: | added: tech-debt |
tags: | added: api |
Changed in maas: | |
assignee: | nobody → Newell Jensen (newell-jensen) |
Changed in maas: | |
status: | Triaged → In Progress |
Changed in maas: | |
status: | In Progress → Fix Committed |
Changed in maas: | |
milestone: | none → 1.6.0 |
Changed in maas: | |
status: | Fix Committed → Fix Released |
Fwiw, ordering in a query string can be relevant, hence why utils.urlencode () accepts an iterable of (name, value) pairs,
apiclient.
and *not* a dict. Passing keyword arguments to get() - even with lists
of arguments - is lossy. However, that doesn't seem to be a concern in
MAAS right now.
So, two approaches I can think of:
1. Change get and co. to accept *args:
def get(self, path, op=None, *args, **kwargs): chain(args, kwargs. viewitems( )))
query = urlencode(
(I'm skipping over the details here; _formulate_get is where the
encoding is done right now.)
2. Change get and co. to munge kwargs before sending off to urlencode:
def flatten(kwargs):
yield name, value
for v in value:
yield name, v
for name, value in kwargs.viewitems():
if isinstance(value, (bytes, unicode)):
else:
def get(self, path, op=None, **kwargs): flatten( kwargs) )
query = urlencode(