Relay is a zero-bloat, fiber-native transport layer designed specifically for PHP 8.5+. It treats HTTP requests as immutable Signals flowing through a Conduit, leveraging the power of native Fibers and the Pipe Operator to deliver non-blocking I/O with a functional API.
- Zero Bloat: No external dependencies. Relay relies solely on
ext-curl. - Fiber Native: Built from the ground up for asynchronous concurrency using PHP's native
Fiberandcurl_multiintegration. - Functional First: Designed for the Pipe Operator (
|>), promoting immutable state and declarative request flows. - Type Safe: Strict typing using native Enums (
Method,Status) and type aliases.
- PHP: 8.5 or higher
- Extensions:
ext-curlext-mbstring
Install Relay via Composer:
composer require juststeveking/relayRelay uses a unique architectural metaphor to describe its components:
- Signal: The atomic unit of communication. It is an Interface implemented by
Success | Failure. You never throw exceptions for HTTP results; you handle the Signal. - Conduit: The pipeline through which a Request transforms into a Signal, typically constructed using the Pipe Operator (
|>). - Transceiver: The component responsible for converting a
Requestinto aSignalby performing the actual network I/O. - WarpCore (Scheduler): The underlying event loop. It manages
curl_multihandles and suspends/resumes Fibers to ensure the main thread never blocks.
Relay requires an active event loop to manage Fibers. Wrap your application entry point in the Scheduler::run method.
use JustSteveKing\Relay\Http\Scheduler;
Scheduler::run(function () {
// ...
});The Client provides a familiar API for managing base URLs, default headers, and middleware stacks.
use JustSteveKing\Relay\Client;
use JustSteveKing\Relay\Http\Middleware\Retry;
use JustSteveKing\Relay\Http\Transceiver;
$client = new Client(
baseUrl: 'https://api.starfleet.org',
defaultHeaders: ['Accept' => 'application/json'],
defaultOptions: ['timeout' => 5], // Seconds
middleware: [
fn($next) => Retry::wrap($next, attempts: 3)
]
);
$signal = $client->get('/sector/001');Requests are immutable. Use the Pipe Operator to send them through the Transceiver.
use JustSteveKing\Relay\Http\Request;
use JustSteveKing\Relay\Http\Transceiver;
use JustSteveKing\Relay\Http\Success;
use JustSteveKing\Relay\Http\Failure;
use JustSteveKing\Relay\Http\Status;
$signal = new Request(
uri: 'https://api.starfleet.org/sector/001',
options: ['allow_redirects' => true]
)
|> Transceiver::send(...);
match(true) {
$signal instanceof Success => printf("Status: %s", $signal->status->name),
$signal instanceof Failure => printf("Alert! %s", $signal->reason),
};Relay provides a functional Auth helper to decorate requests with headers. These are stateless and return a modified clone of the Request.
use JustSteveKing\Relay\Http\Auth;
use JustSteveKing\Relay\Http\Method;
$request = new Request('https://secure.starfleet.org/files', Method::POST);
$signal = $request
|> Auth::bearer('spf-12345-token')
|> Transceiver::send(...);Supported methods:
Auth::bearer(string $token)Auth::basic(string $user, string $pass)Auth::apiKey(string $key, string $header = 'X-API-Key')
Execute multiple requests in parallel using the Concurrent, Pool, or Race helpers.
Basic Concurrency:
use JustSteveKing\Relay\Http\Concurrent;
$results = Concurrent::run([
'profile' => fn() => Transceiver::send($profileReq),
'feed' => fn() => Transceiver::send($feedReq),
]);Concurrency Limiting (Pool):
use JustSteveKing\Relay\Http\Pool;
// Process 100 requests, but only 5 at a time
$results = Pool::work($largeListOfTasks, concurrency: 5);First to Finish (Race):
use JustSteveKing\Relay\Http\Race;
// Returns the first result, discards the rest
$winner = Race::any([
fn() => Transceiver::send($primary),
fn() => Transceiver::send($backup),
]);Encapsulate logic into Action classes. This promotes reusability and clean architecture.
namespace App\Actions;
use JustSteveKing\Relay\Http\Method;
use JustSteveKing\Relay\Http\Request;
use JustSteveKing\Relay\Http\Transceiver;
use JustSteveKing\Relay\Contracts\Signal;
class Starbase
{
public static function hail(string $baseId): Signal
{
// "Immutable mutation" using PHP 8.5 features or the with() helper
return new Request(uri: "https://api.starfleet.org/v1/starbase/{$baseId}")
|> (fn($req) => $req->with(['method' => Method::GET]))
|> Transceiver::send(...);
}
}- Installation: Requirements and setup.
- Core Concepts: Understanding Signals, Conduits, and the WarpCore.
- Usage Guide: Requests, Auth, Middleware, and Pagination.
- Testing: Recording and replaying fixtures.
Check the examples/ directory for ready-to-run scripts:
- Basic Request: Simple GET request handling.
- OAuth Flow: Client Credentials authentication.
- Pagination: Iterating over paginated API results.
Relay is built with high quality standards.
composer testcomposer analysecomposer lint
# or to fix automatically
composer fixRelay is open-sourced software licensed under the MIT license.