ctw / ctw-http
This package provides utility classes and constants to facilitate common operations of PSR-7 and a group of exceptions which represent HTTP status codes.
Installs: 120 314
Dependents: 5
Suggesters: 0
Security: 0
Stars: 1
Watchers: 1
Forks: 1
Open Issues: 0
pkg:composer/ctw/ctw-http
Requires
- php: ^8.3
- fig/http-message-util: ^1.1
Requires (Dev)
- ctw/ctw-qa: ^5.0
- phpunit/phpunit: ^12.0
- symfony/var-dumper: ^7.0
- dev-master
- 4.0.6
- 4.0.5
- 4.0.4
- 4.0.3
- 4.0.2
- 4.0.1
- 4.0.0
- 3.0.24
- 3.0.23
- 3.0.22
- 3.0.21
- 3.0.20
- 3.0.19
- 3.0.18
- 3.0.17
- 3.0.16
- 3.0.15
- 3.0.14
- 3.0.13
- 3.0.12
- 3.0.11
- 3.0.10
- 3.0.9
- 3.0.8
- 3.0.7
- 3.0.6
- 3.0.5
- 3.0.4
- 3.0.3
- 3.0.2
- 3.0.1
- 3.0.0
- 2.0.0
- 1.0.15
- 1.0.14
- 1.0.13
- 1.0.12
- 1.0.11
- 1.0.10
- 1.0.9
- 1.0.8
- 1.0.7
- 1.0.6
- 1.0.5
- 1.0.4
- 1.0.3
- 1.0.2
- 1.0.1
- 1.0.0
This package is auto-updated.
Last update: 2025-11-25 09:46:58 UTC
README
Utility classes, constants, and typed exceptions for PSR-7 HTTP operations, providing a complete HTTP status code registry with metadata and throwable exceptions for all 4xx/5xx status codes.
Introduction
Why This Library Exists
Working with HTTP in PHP often involves scattered magic numbers, inconsistent error handling, and repetitive exception creation. The PSR-7 standard defines message interfaces but doesn't provide status code constants, metadata, or exception types.
This library provides a complete HTTP toolkit:
- Status code constants: All standard HTTP status codes as class constants
- Method constants: HTTP method names (GET, POST, PUT, DELETE, etc.)
- Status metadata: Human-readable names, descriptions, and documentation URLs
- Typed exceptions: Dedicated exception classes for every 4xx and 5xx status code
- Exception hierarchy: Catch client errors (4xx) or server errors (5xx) separately
Problems This Library Solves
- Magic numbers: Code uses
404instead of readableSTATUS_NOT_FOUND - Inconsistent exceptions: Each project invents its own HTTP exception classes
- Missing metadata: Status codes lack human-readable descriptions
- Catch-all handling: No way to catch only client errors vs. server errors
- Documentation gaps: Developers must look up status code meanings externally
Where to Use This Library
- PSR-7 applications: Enhance HTTP message handling with typed constants
- API development: Throw semantically correct HTTP exceptions
- Error handling middleware: Catch exceptions by category (client/server)
- Logging and monitoring: Include status metadata in error reports
- HTTP clients: Use constants instead of magic numbers
Design Goals
- PSR-7 aligned: Implements
Fig\Http\Message\StatusCodeInterface - Complete coverage: All standard HTTP status codes (1xx through 5xx)
- Rich metadata: Name, phrase, and documentation URL for each status
- Exception hierarchy: Abstract base classes for client (4xx) and server (5xx) errors
- Type-safe: Full strict types and interface contracts
Requirements
- PHP 8.3 or higher
- fig/http-message-util ^1.1
Installation
Install by adding the package as a Composer requirement:
composer require ctw/ctw-http
Usage Examples
HTTP Status Metadata
Retrieve complete metadata for any status code:
use Ctw\Http\HttpStatus; $httpStatus = new HttpStatus(HttpStatus::STATUS_NOT_FOUND); $entity = $httpStatus->get(); // Returns: // Ctw\Http\Entity\HttpStatus { // +statusCode: 404 // +name: "Not Found" // +phrase: "The requested resource could not be found but may be available again in the future." // +exception: "Ctw\Http\HttpException\NotFoundException" // +url: "https://httpstatuses.com/404" // }
Throwing HTTP Exceptions
Each 4xx and 5xx status code has a dedicated exception class:
use Ctw\Http\HttpException; // Default message uses status name throw new HttpException\NotFoundException(); // "404 Not Found" // Custom message throw new HttpException\NotFoundException('User with ID 123 not found'); // "User with ID 123 not found" // With custom headers throw new HttpException\UnauthorizedException( message: 'Invalid API key', headers: ['WWW-Authenticate' => 'Bearer'] );
Catching Exceptions by Category
The exception hierarchy allows catching by error category:
use Ctw\Http\HttpException; try { // Application code } catch (HttpException\AbstractClientErrorException $e) { // Handle 4xx errors (client's fault) $statusCode = $e->getStatusCode(); $headers = $e->getHeaders(); } catch (HttpException\AbstractServerErrorException $e) { // Handle 5xx errors (server's fault) } // Or catch all HTTP exceptions try { // Application code } catch (HttpException\HttpExceptionInterface $e) { // Handle any HTTP exception }
Exception Hierarchy
HttpExceptionInterface
└── AbstractException
├── AbstractClientErrorException (4xx)
│ ├── BadRequestException (400)
│ ├── UnauthorizedException (401)
│ ├── ForbiddenException (403)
│ ├── NotFoundException (404)
│ └── ... (all 4xx codes)
└── AbstractServerErrorException (5xx)
├── InternalServerErrorException (500)
├── NotImplementedException (501)
├── BadGatewayException (502)
├── ServiceUnavailableException (503)
└── ... (all 5xx codes)
HTTP Method Constants
use Ctw\Http\HttpMethod; HttpMethod::METHOD_GET; // 'GET' HttpMethod::METHOD_POST; // 'POST' HttpMethod::METHOD_PUT; // 'PUT' HttpMethod::METHOD_PATCH; // 'PATCH' HttpMethod::METHOD_DELETE; // 'DELETE' HttpMethod::METHOD_HEAD; // 'HEAD' HttpMethod::METHOD_OPTIONS; // 'OPTIONS' HttpMethod::METHOD_CONNECT; // 'CONNECT' HttpMethod::METHOD_TRACE; // 'TRACE' HttpMethod::METHOD_PURGE; // 'PURGE'
HTTP Status Constants
use Ctw\Http\HttpStatus; // Informational (1xx) HttpStatus::STATUS_CONTINUE; // 100 HttpStatus::STATUS_SWITCHING_PROTOCOLS; // 101 // Success (2xx) HttpStatus::STATUS_OK; // 200 HttpStatus::STATUS_CREATED; // 201 HttpStatus::STATUS_ACCEPTED; // 202 HttpStatus::STATUS_NO_CONTENT; // 204 // Redirection (3xx) HttpStatus::STATUS_MOVED_PERMANENTLY; // 301 HttpStatus::STATUS_FOUND; // 302 HttpStatus::STATUS_NOT_MODIFIED; // 304 HttpStatus::STATUS_TEMPORARY_REDIRECT; // 307 HttpStatus::STATUS_PERMANENT_REDIRECT; // 308 // Client Error (4xx) HttpStatus::STATUS_BAD_REQUEST; // 400 HttpStatus::STATUS_UNAUTHORIZED; // 401 HttpStatus::STATUS_FORBIDDEN; // 403 HttpStatus::STATUS_NOT_FOUND; // 404 HttpStatus::STATUS_METHOD_NOT_ALLOWED; // 405 HttpStatus::STATUS_CONFLICT; // 409 HttpStatus::STATUS_UNPROCESSABLE_ENTITY; // 422 HttpStatus::STATUS_TOO_MANY_REQUESTS; // 429 // Server Error (5xx) HttpStatus::STATUS_INTERNAL_SERVER_ERROR; // 500 HttpStatus::STATUS_NOT_IMPLEMENTED; // 501 HttpStatus::STATUS_BAD_GATEWAY; // 502 HttpStatus::STATUS_SERVICE_UNAVAILABLE; // 503 HttpStatus::STATUS_GATEWAY_TIMEOUT; // 504
Available Exception Classes
| Status | Exception Class |
|---|---|
| 400 | BadRequestException |
| 401 | UnauthorizedException |
| 402 | PaymentRequiredException |
| 403 | ForbiddenException |
| 404 | NotFoundException |
| 405 | MethodNotAllowedException |
| 406 | NotAcceptableException |
| 407 | ProxyAuthenticationRequiredException |
| 408 | RequestTimeoutException |
| 409 | ConflictException |
| 410 | GoneException |
| 411 | LengthRequiredException |
| 412 | PreconditionFailedException |
| 413 | PayloadTooLargeException |
| 414 | RequestUriTooLongException |
| 415 | UnsupportedMediaTypeException |
| 416 | RangeNotSatisfiableException |
| 417 | ExpectationFailedException |
| 418 | ImATeapotException |
| 421 | MisdirectedRequestException |
| 422 | UnprocessableEntityException |
| 423 | LockedException |
| 424 | FailedDependencyException |
| 425 | TooEarlyException |
| 426 | UpgradeRequiredException |
| 428 | PreconditionRequiredException |
| 429 | TooManyRequestsException |
| 431 | RequestHeaderFieldsTooLargeException |
| 451 | UnavailableForLegalReasonsException |
| 500 | InternalServerErrorException |
| 501 | NotImplementedException |
| 502 | BadGatewayException |
| 503 | ServiceUnavailableException |
| 504 | GatewayTimeoutException |
| 505 | VersionNotSupportedException |
| 506 | VariantAlsoNegotiatesException |
| 507 | InsufficientStorageException |
| 508 | LoopDetectedException |
| 510 | NotExtendedException |
| 511 | NetworkAuthenticationRequiredException |