wilycode / http-response
Typed PSR-7 response factory for HTML, JSON, redirects and empty responses.
Requires
- php: ^8.4
- psr/http-factory: ^1.1
- psr/http-message: ^2.0 || ^1.1
Requires (Dev)
- nyholm/psr7: ^1.8
- phpunit/phpunit: ^11.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-16 06:52:05 UTC
README
Lightweight, typed PSR-7 response creation using PSR-17 factories, with helpers for HTML, JSON, redirects and empty responses.
WilyCode PHP Ecosystem
This library is part of WilyCode, a collection of independent PHP components. Each package has its own repository, Composer installation and releases.
Requirements
- PHP 8.4 or newer.
psr/http-message(PSR-7 contracts) andpsr/http-factory(PSR-17 contracts).- A concrete PSR-7/PSR-17 implementation in your application, such as
nyholm/psr7. The library does not force a specific implementation.
Installation
composer require wilycode/http-response:^0.1
For a standalone project that has no PSR-7/PSR-17 implementation yet, you can additionally install:
composer require nyholm/psr7
Quick start
<?php use Nyholm\Psr7\Factory\Psr17Factory; use WilyCode\Http\Response\HttpStatus; use WilyCode\Http\Response\ResponseFactory; $psr17 = new Psr17Factory(); $responses = new ResponseFactory($psr17, $psr17); $html = $responses->html('<h1>Hello</h1>'); $json = $responses->json(['id' => 15, 'title' => 'Zażółć'], HttpStatus::Created); $redirect = $responses->redirect('/articles'); $noContent = $responses->empty();
All methods return Psr\Http\Message\ResponseInterface. Responses are immutable PSR-7 objects.
Response methods
| Method | Default status | Behavior |
|---|---|---|
html(string $html, HttpStatus $status = HttpStatus::Ok, array $headers = []) |
200 OK |
Sets Content-Type: text/html; charset=utf-8. |
json(array $data, HttpStatus $status = HttpStatus::Ok, array $headers = []) |
200 OK |
JSON-encodes the array and sets Content-Type: application/json; charset=utf-8. |
redirect(string $url, HttpStatus $status = HttpStatus::SeeOther, array $headers = []) |
303 See Other |
Sets a Location header and an empty body. |
empty(HttpStatus $status = HttpStatus::NoContent, array $headers = []) |
204 No Content |
Produces an empty response body. |
JSON responses
$response = $responses->json( ['id' => 15, 'title' => 'Article'], HttpStatus::Created, ['Location' => '/articles/15'], );
JSON output uses JSON_THROW_ON_ERROR, JSON_UNESCAPED_UNICODE, and JSON_UNESCAPED_SLASHES. Invalid JSON values raise JsonException instead of being silently converted. Arrays may contain objects, lists and nested values as supported by json_encode().
Custom headers
$response = $responses->html( '<p>Hello</p>', headers: ['Cache-Control' => 'no-store', 'Content-Type' => 'application/xhtml+xml'], );
json() and html() reject 204 No Content and 304 Not Modified, even when an empty string is passed to html(). Use empty() for bodyless responses. Invalid combinations throw InvalidArgumentException.
Headers accept strings or lists of strings. User-provided headers are applied after defaults, so they override default header values (including differently cased names, as defined by PSR-7).
Redirects
$response = $responses->redirect('/articles'); // 303 See Other $response = $responses->redirect('/articles', HttpStatus::Found); // 302 Found $response = $responses->redirect('/old', HttpStatus::MovedPermanently); // 301 Moved Permanently
Only 301, 302, 303, 307, and 308 are accepted by redirect(). Other status codes raise InvalidArgumentException.
The factory does not validate whether a redirect URL is safe for your application's authorization rules. Validate or restrict user-controlled destinations in your application to avoid open redirects.
Empty responses
$response = $responses->empty(); // 204 No Content $response = $responses->empty(HttpStatus::NotModified); // 304 Not Modified
Status codes
The HttpStatus backed enum exposes the HTTP status code and name:
HttpStatus::Created->value; // 201 HttpStatus::Created->name; // "Created"
Response methods deliberately accept HttpStatus rather than arbitrary integers. The enum includes the common success, redirect, client error and server error statuses. See src/HttpStatus.php for the current set.
Integration
ResponseFactory implements ResponseFactoryInterface, making it suitable for dependency injection. It requires a PSR-17 ResponseFactoryInterface and StreamFactoryInterface in its constructor. You may supply one object that implements both or two separate objects.
The library does not require a router, template engine, session layer, framework or particular PSR-7 implementation.
Development
composer install
composer validate --strict
composer test
Test fixtures use nyholm/psr7 as a development-only dependency. GitHub Actions runs PHPUnit on PHP 8.4.
Tests and CI files are retained in Git but excluded from standard Composer distribution archives. Installing with --prefer-source clones the repository and therefore includes those files.
License
MIT. See LICENSE.