requests / toolbelt

A toolbelt of useful classes and functions to be used with python-requests
https://toolbelt.readthedocs.org
Other
996 stars 184 forks source link

formdata.urlencode does not handle values as list #350

Closed devashish2203 closed 1 year ago

devashish2203 commented 1 year ago

Formdata urlencode does not handle values as strings in the dictionary being encoded

Steps to Reproduce

from requests_toolbelt.utils import formdata

data_works= {
"a": {
      "b": "abc"
    }
}

data_fails = {
"a": {
      "b": ["abc"]
    }
}

print(formdata.urlencode(data_works))
print(formdata.urlencode(data_fails))

The last line above throws the following exception

.../lib/python3.10/site-packages/requests_toolbelt/utils/formdata.py:84: in urlencode
    query_list = _expand_query_values(query_list)
../lib/python3.10/site-packages/requests_toolbelt/utils/formdata.py:107: in _expand_query_values
    query_list.extend((key_fmt % k, v) for k, v in value_list)

.0 = <list_iterator object at 0x14884e260>

>   query_list.extend((key_fmt % k, v) for k, v in value_list)
E   ValueError: too many values to unpack (expected 2)

../lib/python3.10/site-packages/requests_toolbelt/utils/formdata.py:107: ValueError

Expected Output:

a%5Bb%5D%5B%5D=abc

If there were multiple values in the list a%5Bb%5D%5B%5D=abc&a%5Bb%5D%5B%5D=def

devashish2203 commented 1 year ago

351 is a proposed fix for the above. Please let me know if this approach seems okay and I can add/edit tests as needed to get this merged.

sigmavirus24 commented 1 year ago

I'm fairly certain there are many bugs about this on requests and a few here. There is no one right way to handle lists are from lists if a single item. Different server implementations have different expectations. In those cases the user knows what's best and must figure this out themselves

devashish2203 commented 1 year ago

Thanks for the comment. So as per https://github.com/requests/toolbelt/issues/190#issuecomment-319900108 the solution is to send a list of tuples instead of a dict for this use case.