docs+fix: as_curl form-encodes a dict data= body; README notes the commons dependency

as_curl() rendered a dict data= body as its Python repr ({'a': 1}), but aiohttp
form-encodes a dict data= as application/x-www-form-urlencoded (a=1&b=two), so the emitted
curl replayed a different body - now urlencode()s a dict (str bodies unchanged). README
install section omitted the hard sibling commons dependency (a private git+ssh package).

Signed-off-by: disqualifier <dev@disqualifier.me>
This commit is contained in:
2026-07-06 19:37:09 -04:00
parent 85735023f5
commit ed773e2c1b
2 changed files with 8 additions and 2 deletions
+2 -1
View File
@@ -20,7 +20,8 @@ Direct:
pip install "aioweb @ git+ssh://git@git.rethinkstudios.io/rethink-public/aioweb.git@v0.1.13"
```
Requires `aiohttp` and `yarl` (pulled transitively).
Requires `aiohttp` and `yarl` (pulled transitively), plus the sibling `commons` library
(a private `git+ssh` package — the install needs access to the `rethink-public` org).
Drop the `@v0.1.13` suffix from the line above to install the latest unpinned.
+6 -1
View File
@@ -4,6 +4,7 @@ request preview for aioweb - format or export a request without sending it
import json as _json
import shlex
from urllib.parse import urlencode
from yarl import URL
@@ -33,7 +34,11 @@ class RequestPreview:
for header, value in (self.details["headers"] or {}).items():
parts.append(f"-H {shlex.quote(f'{header}: {value}')}")
if self.details["data"] is not None:
parts.append(f"--data {shlex.quote(str(self.details['data']))}")
data = self.details["data"]
# aiohttp form-encodes a dict data= body (application/x-www-form-urlencoded);
# render that wire form, not the python repr, so the curl replays identically
rendered = urlencode(data) if isinstance(data, dict) else str(data)
parts.append(f"--data {shlex.quote(rendered)}")
elif self.details["json"] is not None:
# is-not-None: an empty-but-valid body ({} / []) must still render
parts.append(f"--data {shlex.quote(_json.dumps(self.details['json']))}")