Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistent handling of data sequence values with/without files #360

Open
twm opened this issue Dec 21, 2022 · 1 comment
Open

Inconsistent handling of data sequence values with/without files #360

twm opened this issue Dec 21, 2022 · 1 comment
Labels

Comments

@twm
Copy link
Contributor

twm commented Dec 21, 2022

import os

from twisted.internet.task import react

import treq


async def main(reactor):
    print("Without files:")
    response = await treq.post(
        "https://httpbin.org/post",
        data={"form": ["1", "2"]},
    )
    print(await response.text())

    print("With files:")
    response = await treq.post(
        "https://httpbin.org/post",
        data={"form": ["1", "2"]},
        files={"foo": (os.devnull, open(os.devnull, "rb"))},
    )
    print(await response.text())


react(main, [])

When run:

Without files:
{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "form": [
      "1", 
      "2"
    ]
  }, 
  "headers": {
    "Accept-Encoding": "gzip", 
    "Content-Length": "13", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-63a26dee-580ab8e77fdd228c1eb84266"
  }, 
  "json": null, 
  "origin": "99.187.228.202", 
  "url": "https://httpbin.org/post"
}

With files:
main function encountered error
Traceback (most recent call last):
  File ".../twisted/internet/defer.py", line 696, in callback
    self._startRunCallbacks(result)
  File ".../twisted/internet/defer.py", line 798, in _startRunCallbacks
    self._runCallbacks()
  File ".../twisted/internet/defer.py", line 892, in _runCallbacks
    current.result = callback(  # type: ignore[misc]
  File ".../twisted/internet/defer.py", line 1792, in gotResult
    _inlineCallbacks(r, gen, status, context)
--- <exception caught here> ---
  File ".../twisted/internet/defer.py", line 1697, in _inlineCallbacks
    result = context.run(gen.send, result)
  File ".../demo.py", line 17, in main
    response = await treq.post(
  File ".../src/treq/api.py", line 32, in post
    return _client(kwargs).post(url, data=data, _stacklevel=4, **kwargs)
  File ".../src/treq/client.py", line 182, in post
    return self.request('POST', url, data=data, **kwargs)
  File ".../src/treq/client.py", line 244, in request
    bodyProducer, contentType = self._request_body(data, files, json,
  File ".../src/treq/client.py", line 379, in _request_body
    multipart.MultiPartProducer(data + files, boundary=boundary),
  File ".../src/treq/multipart.py", line 53, in __init__
    self._fields = list(_sorted_by_type(_converted(fields)))
  File ".../src/treq/multipart.py", line 350, in _sorted_by_type
    return sorted(fields, key=key)
  File ".../src/treq/multipart.py", line 260, in _converted
    raise ValueError(
builtins.ValueError: Expected tuple: (filename, content type, producer)

When only data is passed we URL-encode the request body with urllencode(..., doseq=True), whereas when both data and files are passed we combine them and pass the result to MultiPartProducer without unboxing sequences of values.

@twm twm added the bug label Dec 21, 2022
@twm twm changed the title Inconsistent handling of *data* sequence values with/without *files* Inconsistent handling of data sequence values with/without files Dec 21, 2022
@glyph
Copy link
Member

glyph commented Apr 30, 2023

Thanks for filing this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants