A small, modern, PSR-7 compatible PSR-17 and PSR-18 network library for PHP, inspired by Go's net package.

Overview

Net

A small, modern, PSR-7 compatible PSR-17 and PSR-18 network library for PHP, inspired by Go's net package.

Features:

  • No hard dependencies;
  • Favours a BYOB approach to requests & responses;
  • Zero configuration – pure data and interfaces;
  • Testing with third-party APIs made easy;

Setup

Some basic instructions on how to use this in your own project, or contribute to it as a develper.

Requirements

  • PHP >=8.0;
  • Any PSR-7 HTTP message implementation;

Installation

Use composer and access it via your autoloader.

composer require minibase-app/net

For Contributors:

Clone the repository and install the development tools to begin running tests for your features & bug fixes.

git clone https://github.com/minibase-app/net.git \
  && cd ./net \
  && make vendor;

Usage

Here is a snippet which details the most basic setup and usage of the library.

As mentioned earlier in the Requirements and Features, you can use any PSR-7 implementation of your choosing. In all examples from here on out we use Laminas for demonstration, but anything is fine, either hand-rolled or from another library.

use Laminas\Diactoros\{ Request, Response, Uri };
use Minibase\Net\Http;
use Psr\Http\Message\{ RequestInterface, ResponseInterface, UriInterface };

# Initiate a new HTTP instance with PSR-17 requesst & response factory closures
$http = new Http(
    fn (string $method, UriInterface $uri): RequestInterface =>
        new Request($uri, $method),
    fn (mixed $body, int $code, string $reason): ResponseInterface =>
        new Response($body, $code),
);

# Store and fetch a URI instance of your API base URL
$api = new Uri('http://localhost/api');

# Make a request to (any) API and specify resources, queries, etc.
$response = $http->get($api->withPath('users')->withQuery('?_limit=1'));

# Introspect your response
$successful = Http::OK === $response->getStatusCode();

If this isn't a good enough explanation of how this works, don't worry – we will cover each piece in detail next.

Creating a New HTTP Instance

Because this library does not provide (yet another) PSR-7 implemenation, you MUST supply one yourself. This means you can make one, use your company's implementation, or pick your favourite package from the community – in any case it doesn't matter, we only care about the interface.

Once you have a PSR-7 implementation it is time to tell the Http class how it should create requests and responses. This is probably the best part of the library; unlike traditional PHP HTTP "client" libraries, this one does not try to abstract the request/response away into array-based configuration, but instead uses them as a configuration. In other words, your request is it's command, literally...

Let's take a look.

# Here we will make a simple JSON REST API implementation
# Notice that $request and $response are merely PSR-17 factories!
$request = fn (string $method, UriInterface $uri): RequestInterface =>
    new Request($method, $uri, headers: ['content-type' => 'application/json']);
$response = fn (array $body, int $code, string $reason): ResponseInterface =>
    new JsonResponse($body, $code);
$http = new Http($request, $response);

The astute of you, however, will have noticed that the $response closure does not quite adhere to the PSR-17 ResponseFactoryInterface, as it actually receives a body before it gets the code and reason. Rest assured, this interface violation is only present here at the constructor – the Http::createResponse method is implemented as expected, and is done so that you can format as per your requirements.

APIs as URIs

Most HTTP "client" libraries will have some sort of method signature that asks for a URL/endpoint as a string, and provide optional parameters for a query (GET parameters). Often, this can lead to improper use the library by developers placing query parameters directly into the URL/endpoint parameter, using varrying methods of string concatenation and interpolation, leading to unstandardized, and messy code.

In an attempt to prevent this sort of inconsistency from happening (among others you may have experienced), URLs have been done away with in favour of first-class UriInterface instances.

# Store this or a factory for it anywhere along with other API details, like
# auth, headers, etc.!
$github = new Uri('https://api.github.com');

Seems underwhelming at first, but when used with an Http instance configured with some kind of JSON response, we get a fluid and well read set of API calls in our code.

Making Requests

Continuing with the examples from above, let's make a request for a GitHub user profile with ease and style.

$user = $http
  ->get($github->withPath('users/tpope'))
  ->getPayload();

This reads exceptionally well and can be further abstracted as needed, providing an experience much closer to Redis, query builders, and fluid interfaces alike, as opposed to traditional HTTP "client" packages.

Motivation

Yeah, but like ... why?

Good question, and similarly answered; why not? More specifically, and perhaps more seriously, HTTP clients in PHP appear to have a history of being designed very similarily, create their own array-based configuartions, throw exceptions for valid HTTP responses, and have a "top down" approach to creating a client (e.g., new Client('http://api.acme.io')) that can force you to need multiple instances for multiple APIs, all resulting in a cumbersome developer & maintenance experience.

Another point that this library attempts to address is The "Client". We've all had the experience of importing multiple Client classes, aliasing and extending all over the place. "Client" is an amiguous term, similarly to data, and params, essentially meaningless and not even HTTP specific (a client of what?). Inspired by Go's net package, Http just seems like a perfect fit.

Aside from design & usage differences, Net attempts to maintain a slim, concrete, no dependency (PSRs aside), based API that won't result in dependency conflicts during a large-scale project upgrade, that can often happen with legacy projects catching up with latest versions.

You might also like...
Deeper is a easy way to compare if 2 objects is equal based on values in these objects. This library is heavily inspired in Golang's reflect.DeepEqual().

Deeper Deeper is a easy way to compare if 2 objects is equal based on values in these objects. This library is heavily inspired in Golang's reflect.De

Fresns core library: Cross-platform general-purpose multiple content forms social network service software
Fresns core library: Cross-platform general-purpose multiple content forms social network service software

About Fresns Fresns is a free and open source social network service software, a general-purpose community product designed for cross-platform, and su

Allows installing Drupal extensions event if not compatible with installed drupal/core package

mglaman/composer-drupal-lenient Lenient with it, Drupal 10 with it. Why? The Drupal community introduced a lenient Composer facade that modified the d

A small library to help run PHP servers easily and quickly.

PHP Server A small library to help run PHP servers easily and quickly. Installation composer require ahmard/php-server Usage PHP Built-In Server An i

Developer-friendly framework heavily inspired by Laravel and based on Timber and Wpemerge solutions for WordPress themes development with Bedrock folder structure

Lightweight Brocooly (Brocket) Improved Controllers, Middleware and Routers, but slightly less powerful Container Open beta. Package in development Cr

High performance view templating API for PHP applications using tags & expressions inspired by Java JSTL and C compiler

View Language API Table of contents: About Expressions Tags Configuration Compilation Installation Unit Tests Examples Reference Guide About This API

A simple, standalone, modern PHP class inspector and mapper library, wrapping PHPs native reflection in a fluent interface

A simple, standalone, modern PHP class inspector and mapper library, wrapping PHPs native reflection in a fluent interface.

Small utility library that handles metadata minification and expansion.

composer/metadata-minifier Small utility library that handles metadata minification and expansion.

Testing utilities for the psr/log package that backs the PSR-3 specification.

FIG - Log Test Testing utilities for the psr/log package that backs the PSR-3 specification. Psr\Log\Test\LoggerInterfaceTest provides a base test cla

Comments
  • add pooling/deferred (

    add pooling/deferred ("async") request support

    PHP does not do async. Any "async HTTP client" in PHP is really just deferred, and as such we will not use the async/await terminology, but instead defer/dispatch.

    enhancement 
    opened by jordanbrauer 0
Owner
Minibase
A place for miniature and model painters to gain insight into their working habbits & statistics.
Minibase
PeachPie - the PHP compiler and runtime for .NET and .NET Core

PeachPie Compiler The open-source PHP compiler to .NET If you run into any inconsistencies, bugs or incompatibilities, kindly let us know and we'll do

PeachPie Compiler Platform 2.1k Dec 22, 2022
Community-created, unofficial PHP SDK for the Skynet Decentralized Internet Network. siasky.net

Skynet PHP SDK This SDK is a community-created, unofficial SDK in PHP for the Skynet Decentralized Internet Network. It is taken as primarily a port f

Derrick Hammer 4 Dec 26, 2022
Couleur is a modern PHP 8.1+ color library, intended to be compatible with CSS Color Module Level 4.

?? Couleur: A modern PHP 8.1+ color library ?? Couleur: A modern PHP 8.1+ color library ?? Presentation ⚙️ Installation ?? Quick Start ?? Usage ?? Imm

Matthieu Masta Denis 3 Oct 26, 2022
Laravel Blog Package. Easiest way to add a blog to your Laravel website. A package which adds wordpress functionality to your website and is compatible with laravel 8.

Laravel Blog Have you worked with Wordpress? Developers call this package wordpress-like laravel blog. Give our package a Star to support us ⭐ ?? Inst

Binshops 279 Dec 28, 2022
An open source Minecraft server (true-og.net)

true-og An open source Minecraft server (true-og.net) Website forked from aviel900 https://www.spigotmc.org/resources/minecraft-one-page-template.5973

Alex Noyle 0 Nov 28, 2022
A Slack integration to post GIF replies from replygif.net

Archibald Archibald is a Slack integration written in PHP to post tag-selected GIF replies from replygif.net into your current Slack channel or Direct

Lukas Gächter 11 Nov 1, 2020
This is Laravel Framework. Referral User Management System, Payment using Coinpayment.net. etc

About Laravel Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experie

Worlddev5007 12 Aug 26, 2022
Plugin de Wordpress para criar um Hacker News-like para o ManualdoUsuario.net

?? Órbita Plugin de Wordpress para criar um painel de debates baseado em links, similar ao Hacker News, para o Manual do Usuário. Rodar o projeto Requ

Gabriel Nunes 7 Nov 14, 2022
Psl is a standard library for PHP, inspired by hhvm/hsl

?? PHP Standard Library - a modern, consistent, centralized, well-typed, non-blocking set of APIs for PHP programmers

Saif Eddin Gmati 994 Jan 3, 2023
A library for create network applications with PHP.

SocketServer A library for create network applications with PHP. Installation. $ composer require thenlabs/socket-server Usage. The below code show a

ThenLabs 3 Apr 11, 2022