aiohttp has different response to http.client in Python request to API

Context:

This works:

import http.client
conn = http.client.HTTPSConnection("something-api.com")
payload = 'grant_type=client_credentials&client_id=123-123-123&client_secret=123123&scope=something something'
headers = {
'Content-Type': 'application/x-www-form-urlencoded'
}
conn.request("POST", "/connect/token", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))

This does not. It returns { 'error':'invalid_client' }.

async def get_token(self):
    params = {
        "grant_type": "client_credentials",
        "client_id": "123-123-123",
        "client_secret": "123123",
        "scope": "something something"
    }

    headers = {
        "Content-Type": "application/x-www-form-urlencoded",
    }
    
    async with aiohttp.ClientSession() as session:
        async with await session.post(
                url="https://something-api.com/connect/token",
                params=params,
                headers=headers) as response:
            return await response.json()

async def authorise(self):
    response = await self.get_token()
    # Returns { 'error':'invalid_client' }
    return response

# -- Just so you can see how it's called:
authorise_task: tasks.Task = asyncio.create_task(example.authorise())
access_token = await authorise_task

Question:

I cannot understand what the difference is between them. Any ideas what might be happening?

I’ve also tried:

  • Adding headers to the ClientSession(headers=headers) too.
  • Using the URL and removing params

Other notes:

Answer

in docs:

for GET query

params –

Mapping, iterable of tuple of key/value pairs or string to be sent as parameters in the query string of the new request. Ignored for subsequent redirected requests (optional)

Allowed values are:

collections.abc.Mapping e.g. dict, aiohttp.MultiDict or aiohttp.MultiDictProxy

collections.abc.Iterable e.g. tuple or list

str with preferably url-encoded content (Warning: content will not be encoded by aiohttp)

for POST body

data – The data to send in the body of the request. This can be a FormData object or anything that can be passed into FormData, e.g. a dictionary, bytes, or file-like object. (optional)
json – Any json compatible python object (optional). json and data parameters could not be used at the same time.