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

ClientSession does not encode dict params #3999

Closed
rmillet-rs opened this issue Aug 21, 2019 · 2 comments
Closed

ClientSession does not encode dict params #3999

rmillet-rs opened this issue Aug 21, 2019 · 2 comments

Comments

@rmillet-rs
Copy link

Long story short

When passing params as a dict to make client queries, I expect them to be correctly encoded so the original value is retrieved by the server.

Expected behaviour

When passing a dict: params = { 'a': 'A%20B' } to a ClientSession, I expect the query to be formatted as ?a=A%2520B

Actual behaviour

Query looks like ?a=A+B

Steps to reproduce

import aiohttp
import asyncio

params = { 'a': 'A%20B' }
# Same with tuple:
# params = [ ('a', 'A%20B') ]

async def x():
    async with aiohttp.ClientSession() as session:
        async with session.get('http://127.0.0.1/', params=params) as resp:
            print(resp.url)
            print(await resp.text())

asyncio.get_event_loop().run_until_complete(x())

Output:

http://127.0.0.1/?a=A+B
A B

Expected output:

http://127.0.0.1/?a=A%2520B
A%20B

Server side PHP code:

<?php
echo $_GET['a'];

In doc it is written that dict params will be encoded but not str: https://docs.aiohttp.org/en/stable/client_quickstart.html#passing-parameters-in-urls

Your environment

aoihttp client 3.5.4
python 3.6.3

@asvetlov
Copy link
Member

{ 'a': 'A%20B' } is correctly normalized into canonical form ?a=A+B.
If you want to disable normalization please use encoded=True as mentioned in the doc below: https://docs.aiohttp.org/en/stable/client_quickstart.html#passing-parameters-in-urls

@rmillet-rs
Copy link
Author

Hello, if I read well, encoded=True is to use only when we have URL already built: Passing params overrides encoded=True, never use both options.

In my case, I want the client to build the URL and encode my parameters.
And aiohttp doc lets me think, it will do the encoding: You can see that the URL has been correctly encoded by printing the URL. (with a quite simple example with no "strange" character).

It is probably not clear enough but in my example: A%20B is not an URL encoded value, but the raw string I am manipulating. A more concrete example may be params = { 'a': 'Only today: save %20 on my awesome product!' }.

With requests which as a similar syntax, I got the expected behaviour:

from requests import Session

s = Session()
params = { 'a': 'A%20B' }

resp = s.get('http://127.0.0.1/', params=params)
print(resp.url)
print(resp.text)

Outputs:

http://127.0.0.1/?a=A%2520B
A%20B

If it is a limitation, it should at least be indicated in the doc.

It seems to be related to aio-libs/yarl#181

Cheers

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

No branches or pull requests

2 participants