Files
responder/tests/test_redirect_default.py
kennethreitz ea5ba0d26b Add standalone Router composition; fix lifespan/dispatch/header correctness; 8.0 behavior changes
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>
2026-07-01 17:05:08 -04:00

71 lines
1.9 KiB
Python

"""Response.redirect() defaults to 307, with permanent=True selecting 308."""
def test_redirect_defaults_to_temporary_307(api):
@api.route("/old")
def old(req, resp):
resp.redirect("/new")
r = api.requests.get("/old", follow_redirects=False)
assert r.status_code == 307
assert r.headers["Location"] == "/new"
def test_redirect_permanent_selects_308(api):
@api.route("/old")
def old(req, resp):
resp.redirect("/new", permanent=True)
r = api.requests.get("/old", follow_redirects=False)
assert r.status_code == 308
assert r.headers["Location"] == "/new"
def test_explicit_status_code_still_wins(api):
@api.route("/moved")
def moved(req, resp):
resp.redirect("/new", status_code=301)
@api.route("/found")
def found(req, resp):
resp.redirect("/new", status_code=302, permanent=True)
assert api.requests.get("/moved", follow_redirects=False).status_code == 301
# An explicit status_code takes precedence over permanent=.
assert api.requests.get("/found", follow_redirects=False).status_code == 302
def test_api_redirect_helper_matches_new_default(api):
@api.route("/a")
def a(req, resp):
api.redirect(resp, location="/b")
@api.route("/p")
def p(req, resp):
api.redirect(resp, location="/b", permanent=True)
assert api.requests.get("/a", follow_redirects=False).status_code == 307
assert api.requests.get("/p", follow_redirects=False).status_code == 308
def test_redirect_still_follows(api, session):
@api.route("/2")
def two(req, resp):
resp.redirect("/1")
@api.route("/1")
def one(req, resp):
resp.text = "redirected"
r = session.get("/2")
assert r.text == "redirected"
def test_redirect_sets_body_text(api):
@api.route("/old")
def old(req, resp):
resp.redirect("/new")
r = api.requests.get("/old", follow_redirects=False)
assert r.text == "Redirecting to: /new"