fix: preview() works without a running loop; set_cookie honors path when domain=None
preview()'s default cookie lookup reached the backend session and could force-
build it, raising RuntimeError('no running event loop') off-loop and defeating
the v0.1.7 lazy-session pre-loop use case; it's now skipped when the session
isn't built yet. set_cookie(domain=None) returned before setting the morsel's
path, so a shared cookie always stored path='/' regardless of the path= arg;
the morsel path is now set before that early return.
Signed-off-by: disqualifier <dev@disqualifier.me>
This commit is contained in:
@@ -11,18 +11,18 @@ and swap the HTTP client while inheriting everything else.
|
||||
`requirements.txt`:
|
||||
|
||||
```
|
||||
aioweb @ git+ssh://git@git.rethinkstudios.io/rethink-public/aioweb.git@v0.1.10
|
||||
aioweb @ git+ssh://git@git.rethinkstudios.io/rethink-public/aioweb.git@v0.1.11
|
||||
```
|
||||
|
||||
Direct:
|
||||
|
||||
```bash
|
||||
pip install "aioweb @ git+ssh://git@git.rethinkstudios.io/rethink-public/aioweb.git@v0.1.10"
|
||||
pip install "aioweb @ git+ssh://git@git.rethinkstudios.io/rethink-public/aioweb.git@v0.1.11"
|
||||
```
|
||||
|
||||
Requires `aiohttp` and `yarl` (pulled transitively).
|
||||
|
||||
Drop the `@v0.1.10` suffix from the line above to install the latest unpinned.
|
||||
Drop the `@v0.1.11` suffix from the line above to install the latest unpinned.
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -97,10 +97,15 @@ s.overwrite_domain("internal.local", "127.0.0.1") # host-substring rewrite
|
||||
print(s.preview("POST", url, json={"a": 1}).as_curl()) # equivalent cURL command
|
||||
```
|
||||
|
||||
`as_curl()` renders `params` (merged into the url's query string) and `timeout` (as
|
||||
`--max-time`) as well as headers/body/proxy, so the emitted command is faithful to what
|
||||
`request()` actually sends. Pass `debug=True` to `request_with_retries` to log the cURL
|
||||
preview and request flow.
|
||||
`preview()` is synchronous and never touches the backend session — it works before any
|
||||
event loop is running (e.g. building a preview at import/setup time), not just inside
|
||||
`asyncio.run()`. Its default cookie lookup only reads cookies from an already-built
|
||||
session; if the session hasn't been built yet there are no cookies to read, so it
|
||||
returns none by default (pass `cookies=` explicitly to preview cookies for a session
|
||||
that hasn't sent a request yet). `as_curl()` renders `params` (merged into the url's
|
||||
query string) and `timeout` (as `--max-time`) as well as headers/body/proxy, so the
|
||||
emitted command is faithful to what `request()` actually sends. Pass `debug=True` to
|
||||
`request_with_retries` to log the cURL preview and request flow.
|
||||
|
||||
## Custom backends
|
||||
|
||||
@@ -144,6 +149,23 @@ Two changes can't be shimmed without re-introducing the bugs they fix:
|
||||
|
||||
## Changelog
|
||||
|
||||
### v0.1.11
|
||||
|
||||
- **`preview()` no longer requires a running event loop.** Its default cookie
|
||||
lookup (`cookies=` not passed) previously called `_cookies_for_url()`, which
|
||||
reached the backend session and built it if absent — under aiohttp>=3.14 that
|
||||
needs a running loop, so `preview()` raised `RuntimeError('no running event
|
||||
loop')` when called before the loop starts, defeating its own pre-loop
|
||||
build/inspect use case (v0.1.7). Now the default cookie lookup is skipped
|
||||
entirely when the session hasn't been built yet (nothing could have been set
|
||||
on a session that doesn't exist); `cookies={}` and in-loop calls are unaffected.
|
||||
- **`set_cookie(domain=None)` now honors `path`.** The `domain=None` branch
|
||||
returned right after `update_cookies()`, before the line that sets the
|
||||
morsel's `path` — so a shared cookie (`set_cookie(name, value, path="/api")`,
|
||||
no `domain=`) always stored the `SimpleCookie` default `path="/"` instead. The
|
||||
morsel's `path` is now set before the `domain=None` early return. The
|
||||
domain-bound branch was already correct and is unchanged.
|
||||
|
||||
### v0.1.10
|
||||
|
||||
- Docs-only pass: compressed module/method docstrings and comments that restated
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "aioweb"
|
||||
version = "0.1.10"
|
||||
version = "0.1.11"
|
||||
description = "Async HTTP session wrapper over aiohttp — proxies, header overwrites, retries, previews. Config-free, installable."
|
||||
requires-python = ">=3.10"
|
||||
dependencies = [
|
||||
|
||||
@@ -227,12 +227,12 @@ class ExtendedSession:
|
||||
"""
|
||||
cookie = SimpleCookie()
|
||||
cookie[name] = value
|
||||
cookie[name]["path"] = path
|
||||
if domain is None:
|
||||
self.session.cookie_jar.update_cookies(cookie)
|
||||
return
|
||||
if "://" not in domain:
|
||||
domain = "http://" + domain
|
||||
cookie[name]["path"] = path
|
||||
self.session.cookie_jar.update_cookies(cookie, response_url=URL(domain))
|
||||
|
||||
def clear_cookies(self):
|
||||
@@ -247,11 +247,15 @@ class ExtendedSession:
|
||||
# preview
|
||||
|
||||
def preview(self, method, url, **kwargs):
|
||||
"""build a RequestPreview for a request without sending it
|
||||
"""build a RequestPreview for a request without sending it - synchronous, no loop required
|
||||
|
||||
url is domain-rewritten before cookies are resolved, matching the real
|
||||
request - cookie binding is host-based, so resolving against the pre-rewrite
|
||||
host could miss or misattribute cookies.
|
||||
host could miss or misattribute cookies. the default cookie lookup never
|
||||
touches the backend session: building it needs a running loop (aiohttp>=3.14),
|
||||
which would defeat preview()'s own pre-loop inspection use case, and an unbuilt
|
||||
session has no cookies to report anyway - pass cookies= explicitly to preview
|
||||
cookies that would come from a not-yet-built session.
|
||||
"""
|
||||
url = self._apply_domain_overwrites(url)
|
||||
proxy = self._get_proxy(url, kwargs.pop("proxies", None))
|
||||
@@ -262,7 +266,7 @@ class ExtendedSession:
|
||||
timeout_total = timeout if isinstance(timeout, (int, float)) else None
|
||||
|
||||
cookies = kwargs.pop("cookies", None)
|
||||
if cookies is None:
|
||||
if cookies is None and self._session is not None:
|
||||
cookies = self._cookies_for_url(url)
|
||||
if cookies:
|
||||
cookie_header = "; ".join(f"{k}={v}" for k, v in cookies.items())
|
||||
|
||||
Reference in New Issue
Block a user