use InitPHP\HTTP\Message\Response;
$response = (new Response())->redirect('https://example.com/new-home', 301);Sets Location: https://example.com/new-home and status 301. Use 301 for SEO-relevant moves that you want cached by search engines and browsers.
$response = (new Response())->redirect('/dashboard', 302);302 (Found) is what most "after login, send the user back" flows use. If you specifically need the client to preserve the request method (e.g. POST → POST), use 307 (Temporary Redirect):
$response = (new Response())->redirect('/checkout', 307);After processing a POST, send 303 to force the browser to do a GET on the next URL — the classic anti-double-submit pattern:
$response = (new Response())->redirect('/orders/' . $orderId, 303);For "thanks, redirecting in 5 seconds" pages:
$response = (new Response())->redirect('https://example.com/thanks', 200, 5);Location is still set (for crawlers and non-browser clients) plus Refresh: 5; url=https://example.com/thanks for browsers that honour the countdown. The status defaults to 302 if you don't pass one; the example above uses 200 so the page body actually renders during the wait.
PSR-7 leaves cookie handling to your session middleware; if you need to preserve a session across the redirect, set it on the response before emitting:
$response = (new Response())
->redirect('/dashboard', 302)
->withAddedHeader('Set-Cookie', 'PHPSESSID=' . session_id() . '; Path=/; HttpOnly');redirect() throws InvalidArgumentException if you pass anything that isn't a string or a Psr\Http\Message\UriInterface:
try {
$response = (new Response())->redirect(42);
} catch (\InvalidArgumentException $e) {
// "URI is not valid."
}