HTTP response
Response is mutable and is not an immutable PSR-7 response. Every with*() returns the same instance. Create a response per request; never share a mutable response between clients.
Headers and cookies
Section titled “Headers and cookies”header()/withHeader() and withHeaders() mutate the map. getHeader() and withoutHeader() match names case-insensitively, but writes preserve supplied casing: avoid duplicate names with different casing. getHeaders() returns the map. Serialization strips CR/LF from names/values; do not treat that as permission to accept arbitrary user-controlled headers.
cookie($name, $value, $maxAge, $path, $domain, $secure, $httpOnly, $sameSite) appends Set-Cookie and encodes name/value. Time means Max-Age in seconds, not a Unix timestamp. Set appropriate Secure/HttpOnly/SameSite and scope for authentication cookies; the application owns CSRF protection.
Files and conditional requests
Section titled “Files and conditional requests”withFile($path, $offset = 0, $length = 0) prepares metadata; the HTTP codec performs transmission, not (string)$response. Missing/unreadable files produce 404. Negative offsets/lengths are rejected. Resolve paths inside authorized storage after access checks, never by concatenating an unchecked URL.
withFileForRequest($request, $path) handles GET/HEAD, preconditions (412), validators (304) and a single byte range (416 if unsatisfiable). Multiple ranges fall back to a full response; multipart/byteranges is not generated. Successful ranges remain metadata for the codec. ETag uses mtime/size, not a content hash.
Compression and streaming
Section titled “Compression and streaming”withCompressionForRequest($request, $minBytes = 1024, $level = -1) explicitly enables gzip and accounts for q-values, Range, no-transform, existing encoding/stream/file and actual size reduction. Assess length leaks before compressing secrets together with reflected input.
withChunkedTransfer() removes Content-Length and clears the body. Send headers once, then Chunk objects, ending with an empty Chunk; do not send another Response for each event. See the executable SSE recipe.