encode / httpx

A next generation HTTP client for Python. 🦋

Home Page:https://www.python-httpx.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Httpx behaving differently than requests?

EricPanDev opened this issue · comments

the data paramater in httpx.post and httpx.client.post behave differently than requests.post

Example with discord's API:

This will not work

import httpx

header = {
    'Authorization': "Bot token",
}

files = {
    "file": ("hi.png", open("./image.png", 'rb'), "image/png")
}

payload = {
    "content": "pls work",
    "allowed_mentions": {
        "parse": []
    }
}

channel_id = "1079501847720640682"

r = httpx.post(f"https://discord.com/api/v9/channels/{channel_id}/messages", data=payload, headers=header, files=files)

print(r.status_code)
print(r.text)

However with requests, this will work fine

import requests

header = {
    'Authorization': "Bot token",
}

files = {
    "file": ("hi.png", open("./image.png", 'rb'), "image/png")
}

payload = {
    "content": "pls work",
    "allowed_mentions": {
        "parse": []
    }
}

channel_id = "1079501847720640682"

r = requests.post(f"https://discord.com/api/v9/channels/{channel_id}/messages", data=payload, headers=header, files=files)

print(r.status_code)
print(r.text)

I am unsure if this is a bug or if I need to pass these arguments differently in httpx

Here is the console output

eric@Erics-MacBook-Air Gen5 % /usr/bin/python3 
/Users/eric/Documents/Gen5/test.py
Traceback (most recent call last):
  File "/Users/eric/Documents/Gen5/test.py", line 20, in <module>
    r = httpx.post(f"https://discord.com/api/v9/channels/{channel_id}/messages", data=payload, headers=header, files=files)
  File "/Users/eric/Library/Python/3.9/lib/python/site-packages/httpx/_api.py", line 319, in post
    return request(
  File "/Users/eric/Library/Python/3.9/lib/python/site-packages/httpx/_api.py", line 106, in request
    return client.request(
  File "/Users/eric/Library/Python/3.9/lib/python/site-packages/httpx/_client.py", line 814, in request
    request = self.build_request(
  File "/Users/eric/Library/Python/3.9/lib/python/site-packages/httpx/_client.py", line 357, in build_request
    return Request(
  File "/Users/eric/Library/Python/3.9/lib/python/site-packages/httpx/_models.py", line 340, in __init__
    headers, stream = encode_request(
  File "/Users/eric/Library/Python/3.9/lib/python/site-packages/httpx/_content.py", line 208, in encode_request
    return encode_multipart_data(data or {}, files, boundary)
  File "/Users/eric/Library/Python/3.9/lib/python/site-packages/httpx/_content.py", line 153, in encode_multipart_data
    multipart = MultipartStream(data=data, files=files, boundary=boundary)
  File "/Users/eric/Library/Python/3.9/lib/python/site-packages/httpx/_multipart.py", line 211, in __init__
    self.fields = list(self._iter_fields(data, files))
  File "/Users/eric/Library/Python/3.9/lib/python/site-packages/httpx/_multipart.py", line 221, in _iter_fields
    yield DataField(name=name, value=value)
  File "/Users/eric/Library/Python/3.9/lib/python/site-packages/httpx/_multipart.py", line 50, in __init__
    raise TypeError(
TypeError: Invalid type for value. Expected primitive type, got <class 'dict'>: {'parse': []}

the APIs are slightly different, it looks like httpx typehints the data kwarg as a Mapping[str, Any] but requests is a straight dict

I mean it works fine if the dict passed to the data paramater only has one item in httpx, but if I have 2 or more keys it raises that error