API Design
Embracing PSRs to build an interoperable HTTP Client
Learn to build a PSR-18 compliant HTTP client in PHP, enhancing web development through interoperability and efficient request handling.
May 20202 min read
Recently I have been scratching my head over PSR-18. As a new PSR there isn’t a lot of information around it, but I saw that as a challenge. I decided to accept this challenge and build a compliant HTTP client to embrace the future of interoperability.
If you look at the specifications for PSR-18 on PHP-FIG they are typically pretty confusing, but I read between the lines a little. The first step was to build a class that would accept all the necessary components to bootstrap the client.
namespace JustSteveKing\HttpSlim;
use Psr\Http\Message\StreamFactoryInterface;use Psr\Http\Message\RequestFactoryInterface;use Psr\Http\Client\ClientExceptionInterface;
class HttpClient implements HttpClientInterface{ protected ClientInterface $client; protected StreamFactoryInterface $streamFactory; protected RequestFactoryInterface $requestFactory;}Now if you have read any of my other posts, or used any of my packages, or seen my posts on twitter, you will know I am a huge fan of named constructors.
final protected function __construct( ClientInterface $client, RequestFactoryInterface $requestFactory, StreamFactoryInterface $streamFactory) { $this->client = $client; $this->requestFactory = $requestFactory; $this->streamFactory = $streamFactory;}
public static function build( ClientInterface $client, RequestFactoryInterface $requestFactory, StreamFactoryInterface $streamFactory): self { return new static( $client, $requestFactory, $streamFactory );}This gives us a good starting point to begin with, from here we can implement our helper methods for making requests and encoding json. Our helper methods follow a typical pattern of, take a URL and an optional body as an array - making sure that we return a PSR-7 compliant Response (but that it typically down to the client library we inject). Here is an example of the post request:
use \JsonException;use Psr\Http\Message\ResponseInterface;use JustSteveKing\HttpSlim\Exceptions\RequestError;
public function post(string $uri, array $body): ResponseInterface{ // build out json body content try { $content = $this->encodeJson($body); } catch (JsonException $exception) { throw RequestError::invalidJson($exception); }
$request = $this->requestFactory ->createRequest('POST', $uri) ->withAddedHeader('Content-Type', 'application/json') ->withBody($this->streamFactory->createStream($content));
return $this->client->sendRequest($request);}Our encodeJson method simply returns a json encoded version of the passed through array.
This is just one adventure into embracing PSRs, but I have thoroughly enjoyed it so far! Please drop me a tweet if you have found this useful at all, or if you find an issue - feel free to drop an issue on the GitHub repo
Related
More in API Design
Most of Your SDK Has Already Been Designed, Too
Retries, rate limits, pagination, lost updates: the API already tells your client what to do. sdk-toolbox makes a PHP SDK listen, one RFC at a time.
Oct 2026 · 19 min read
API DesignAn Example App That Needs Its Features
Flagpole is a feature flag service built on kit, where every HTTP standard is there because the domain needs it. Building it found four bugs that kit's own tests never caught.
Oct 2026 · 6 min read
API DesignA Laravel API Starter Kit That Keeps Its Promises
Starter kits are right on the day you install them and drift from then on. Kit now checks its own promises in CI, so the docs, spec, errors and dependencies stay true.
Oct 2026 · 12 min read
Same subject
In other formats
http-slim
A slim psr compliant http client to provide better interoperability.
API Design
VideoBuild a CLI app with Laravel Zero - Todoist API Integration
🚀 Join me LIVE as we dive into the world of command-line interface (CLI) applications using Laravel Zero! In this session, we'll craft a sleek, functional CLI app designed to work seamlessly with the
API Design