mirror of
https://github.com/kennethreitz/responder.git
synced 2026-07-21 18:39:29 +00:00
ea5ba0d26b
The first 8.0 sweep. Flagship: responder.Router records route declarations without an API instance (Flask-blueprint style) and api.include_router() replays them with prefix/tags/dependencies/auth composition, nesting, and conflict guards. Correctness: lifespan= now composes with on_event (background draining runs again), view-style default routes dispatch instead of 500ing, CBV HEAD falls back to on_get, tolerant cookie parsing, case-insensitive resp.headers, async background tasks, async GraphQL resolvers, Jinja builtins survive context assignment, identity-based dependency cycle detection, WSGI mounts wrap once, WebSocket crashes send a 1011 close frame, and dependency metadata matches actual imports. Security: Content-Disposition filename escaping in resp.download(); bounded, lock-guarded MemorySessionBackend with expiry-first eviction. 8.0 behavior changes: no implicit static/ mkdir, url_for raises RouteNotFoundError and percent-encodes values, redirect() defaults to 307 (permanent=True for 308), charset= on encoded text responses (no more fake 'Encoding' header), and RFC 9512 application/yaml. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
45 lines
1.3 KiB
Python
45 lines
1.3 KiB
Python
"""Request.cookies uses tolerant cookie parsing (not SimpleCookie)."""
|
|
|
|
|
|
def test_nonconforming_cookie_token_does_not_drop_later_cookies(api):
|
|
# http.cookies.SimpleCookie aborts at the first nonconforming token
|
|
# (here "b[]"), silently dropping every cookie after it.
|
|
@api.route("/")
|
|
def view(req, resp):
|
|
resp.media = req.cookies
|
|
|
|
r = api.requests.get("/", headers={"Cookie": "a=1; b[]=2; c=3"})
|
|
cookies = r.json()
|
|
assert cookies["a"] == "1"
|
|
assert cookies["c"] == "3"
|
|
|
|
|
|
def test_plain_cookies_still_parse(api):
|
|
@api.route("/")
|
|
def view(req, resp):
|
|
resp.media = req.cookies
|
|
|
|
r = api.requests.get("/", headers={"Cookie": "hello=world; foo=bar"})
|
|
assert r.json() == {"hello": "world", "foo": "bar"}
|
|
|
|
|
|
def test_no_cookie_header_yields_empty_dict(api):
|
|
@api.route("/")
|
|
def view(req, resp):
|
|
resp.media = {"cookies": req.cookies}
|
|
|
|
r = api.requests.get("/")
|
|
assert r.json() == {"cookies": {}}
|
|
|
|
|
|
def test_cookies_are_cached_per_request(api):
|
|
@api.route("/")
|
|
def view(req, resp):
|
|
first = req.cookies
|
|
first["injected"] = "yes"
|
|
# The property caches, so the same dict comes back.
|
|
resp.media = {"same": req.cookies is first}
|
|
|
|
r = api.requests.get("/", headers={"Cookie": "a=1"})
|
|
assert r.json() == {"same": True}
|