Skip to content

effectra/http-message

Repository files navigation

Effectra HTTP Message

A PSR-7 HTTP message library for PHP 8.1+.

Installation

composer require effectra/http-message

Requirements

  • PHP ^8.1
  • psr/http-message ^1.1 || ^2.0

Package Features

  • PSR-7 compliantRequest, Response, ServerRequest, Uri, Stream, UploadedFile, Message
  • Case-insensitive headershasHeader(), getHeader(), withHeader(), etc. all normalize to lowercase
  • Immutable with* methods — all PSR-7 with* methods return new instances; mutable set* methods are also available
  • Response factorieswithJson(), static json(), static html(), static emptyResponse()
  • ServerRequest utilitiesfromGlobals() factory, replaceHeader() helper
  • Stream from file path — constructor accepts a file path string and opens it as a resource
  • UploadedFilegetStream() reads from the actual uploaded file
  • PHP 8 featuresfinal classes, readonly properties, #[Immutable] attribute
  • Comprehensive test suite — 196+ tests, PHPStan level 6 clean

Usage

Creating a Request

use Effectra\Http\Message\Request;
use Effectra\Http\Message\Uri;

$uri = new Uri('https://api.example.com/users');
$request = new Request('POST', $uri, ['Content-Type' => 'application/json'], '{"name":"John"}');

echo $request->getMethod();                 // POST
echo $request->getHeaderLine('Content-Type'); // application/json

Immutable with* methods:

$new = $request->withMethod('PUT')->withUri(new Uri('https://other.com'));
// $request is unchanged

Mutable set* methods:

$request->setMethod('PATCH')->setUri(new Uri('/local'));
// $request is modified in place

Creating a Response

use Effectra\Http\Message\Response;

$response = new Response(200, ['X-Custom' => 'value'], 'OK');
echo $response->getStatusCode();              // 200
echo $response->getReasonPhrase();            // OK

Response Factories

// JSON response
$res = Response::json(['status' => 'ok']);
$res = (new Response())->withJson(['error' => 'bad'], 400);

// HTML response
$res = Response::html('<h1>Hello</h1>', 200);

// Empty response (e.g. 204 No Content)
$res = Response::emptyResponse(204);

All standard HTTP status codes (100–511) are available as class constants:

Response::HTTP_OK;               // 200
Response::HTTP_NOT_FOUND;        // 404
Response::HTTP_I_AM_A_TEAPOT;    // 418

ServerRequest (from globals)

use Effectra\Http\Message\ServerRequest;

$request = ServerRequest::fromGlobals();

echo $request->getMethod();          // GET, POST, etc.
echo $request->getServerParams()['REMOTE_ADDR'];
$input = $request->getParsedBody();  // POST / JSON body

Working with URIs

use Effectra\Http\Message\Uri;

$uri = new Uri('https://example.com/path?q=hello#section');

echo $uri->getScheme();    // https
echo $uri->getHost();      // example.com
echo $uri->getPath();      // /path
echo $uri->getQuery();     // q=hello

$new = $uri->withScheme('http')->withHost('other.org');

Stream

use Effectra\Http\Message\Stream;

// From a string
$stream = new Stream('content');
echo $stream->getContents(); // content

// From a file path (opens automatically)
$stream = new Stream('/path/to/file.txt');

// From a resource
$stream = new Stream(fopen('php://memory', 'r+'));
$stream->write('data');

Uploaded Files

use Effectra\Http\Message\UploadedFile;

$file = new UploadedFile(
    $_FILES['avatar']['tmp_name'],
    $_FILES['avatar']['size'],
    $_FILES['avatar']['error'],
    $_FILES['avatar']['name'],
    $_FILES['avatar']['type']
);

$stream = $file->getStream();            // read file contents
echo $file->getClientFilename();         // original name
$file->moveTo('/storage/avatars/1.jpg');

Case-Insensitive Headers

All header operations are case-insensitive:

$request = new Request('GET', '/', ['Content-Type' => 'text/html']);

$request->hasHeader('content-type');     // true
$request->hasHeader('CONTENT-TYPE');     // true
$request->hasHeader('Content-Type');     // true

$request->getHeader('CONTENT-TYPE');     // ['text/html']

$cloned = $request->withoutHeader('content-type');
$cloned = $request->withAddedHeader('X-Custom', 'val');

Attributes (PHP 8)

use Effectra\Http\Message\Attribute\Immutable;

#[Immutable('This class follows the PSR-7 immutable pattern')]
class MyMessage
{
    // ...
}

#[Immutable] and #[Deprecated] attributes are available for documentation and static analysis.

PHPStan

composer run phpstan

Level 6 with baseline. The _ide_helper.php file provides additional type information for better IDE support.

Testing

composer test

Contributing

Contributions are welcome. Please open an issue or submit a pull request.

License

MIT

About

Effectra/Http-Message: A PHP library implementing PSR-7 for standardized handling of HTTP requests and responses.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages