GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — GitHub - InitPHP/HTTP: Standards-compliant PSR-7, PSR-17, PSR-18 HTTP messages, factories, cURL client, and SAPI response emitter for PHP 7.4+ (PSR-7 v1 & v2 compatible).

BranchesTags
Open more actions menu

Latest commit

 

History

26 Commits
26 Commits

Folders and files

NameName
Last commit message
Last commit date
.github
.github
 
 
docs
docs
 
 
src
src
 
 
tests
tests
 
 
.editorconfig
.editorconfig
 
 
.gitignore
.gitignore
 
 
CHANGELOG.md
CHANGELOG.md
 
 
LICENSE
LICENSE
 
 
README.md
README.md
 
 
composer.json
composer.json
 
 
phpstan.neon.dist
phpstan.neon.dist
 
 
phpunit.xml.dist
phpunit.xml.dist
 
 

Repository files navigation

InitPHP HTTP

Standards-compliant PSR-7 message, PSR-17 factory, PSR-18 client and SAPI response emitter for PHP 7.4+.

Designed & Maintained with Tan Latest Stable Version Total Downloads License PHP Version Require Tests Static Analysis

A single dependency-light package that ships the four building blocks every PHP project ends up wiring by hand: immutable HTTP messages, a unified factory, a cURL-backed client, and an emitter that converts a ResponseInterface into bytes on the wire.

composer require initphp/http
use InitPHP\HTTP\Facade\Factory;
use InitPHP\HTTP\Facade\Emitter;

$response = Factory::createResponse(200, 'OK')
    ->withHeader('Content-Type', 'text/plain; charset=utf-8');
$response->getBody()->write('Hello, world!');

Emitter::emit($response);

Table of Contents

  • Features
  • Requirements
  • Installation
  • Quick Start
    • Building a PSR-7 Request
    • Building a PSR-7 Response
    • Sending an HTTP request (PSR-18)
    • Emitting a response (SAPI)
    • Hydrating a ServerRequest from globals
    • Using the static facades
  • Documentation
  • PSR Compliance
  • Migration from 2.x
  • Contributing
  • Security
  • License

Features

  • PSR-7 v1 & v2 compatible — works with the entire PSR-7 ecosystem.
  • PSR-17 factory — one class implements every factory interface (Request, Response, ServerRequest, Stream, UploadedFile, Uri).
  • PSR-18 client backed by cURL with sane production defaults: 30 s request timeout, 10 s connect timeout, redirect following, raw CURLOPT_* overrides without subclassing.
  • SAPI emitter that streams the response to the browser with optional chunked output and Content-Range support.
  • Lazy static facades for projects that prefer Factory::createResponse() over instantiating helpers explicitly.
  • Strict PSR-7 immutability — with*() returns deep-cloned messages; mutating the clone never touches the original (verified by a dedicated immutability test suite).
  • Zero runtime dependencies outside psr/http-*. ext-curl is only required when you actually use the client.
  • Passes the upstream php-http/psr7-integration-tests and http-interop/http-factory-tests suites.

Requirements

Component Minimum
PHP 7.4
ext-json always required
ext-curl required by InitPHP\HTTP\Client\Client (PSR-18 transport)
psr/http-message `^1.0
psr/http-factory ^1.0
psr/http-client ^1.0

Tested on PHP 7.4, 8.0, 8.1, 8.2, 8.3 and 8.4 in CI.

Installation

composer require initphp/http

Quick Start

Building a PSR-7 Request

use InitPHP\HTTP\Message\Request;

$request = new Request(
    'POST',
    'https://api.example.com/users',
    ['Accept' => 'application/json'],
    json_encode(['name' => 'Ada']),
    '1.1'
);

$request = $request->withHeader('Content-Type', 'application/json; charset=utf-8');

Building a PSR-7 Response

use InitPHP\HTTP\Message\Response;

$response = (new Response())
    ->withStatus(201, 'Created')
    ->withHeader('Location', '/users/42');

$response->getBody()->write('{"id":42}');

Convenience producers on the concrete Response:

$response = (new Response())->json(['id' => 42], 201);
$response = (new Response())->redirect('https://example.com/welcome', 302);

Sending an HTTP request (PSR-18)

use InitPHP\HTTP\Client\Client;
use InitPHP\HTTP\Message\Request;

$client = (new Client())
    ->withTimeout(10)
    ->withConnectTimeout(3)
    ->withUserAgent('my-app/1.0');

$response = $client->sendRequest(
    new Request('GET', 'https://httpbin.org/get')
);

echo $response->getStatusCode();          // 200
echo (string) $response->getBody();       // {"args":{},"headers":{...},...}

Higher-level helpers when you don't want to build a Request by hand:

$response = $client->get('https://api.example.com/users');
$response = $client->post('https://api.example.com/users', '{"name":"Ada"}', [
    'Content-Type' => 'application/json',
]);

PSR-18 contract is honoured: 4xx/5xx responses are returned, not thrown. Only transport failures raise Psr\Http\Client\NetworkExceptionInterface.

Resilience: retry with exponential backoff + jitter

The client is single-attempt by default. Attach a RetryPolicy to opt in to automatic retries of transient failures — connection errors, timeouts and the retryable HTTP status set (408, 425, 429, 500, 502, 503, 504 by default) — with exponential backoff, bounded jitter, a hard max-attempts cap, and Retry-After support:

use InitPHP\HTTP\Client\Client;
use InitPHP\HTTP\Client\Retry\RetryPolicy;

$client = (new Client())->withRetryPolicy(new RetryPolicy(
    maxAttempts: 4,        // 1 initial try + up to 3 retries
    baseDelay:   0.1,      // first backoff interval, seconds
    multiplier:  2.0,      // 0.1s, 0.2s, 0.4s, ...
    maxDelay:    30.0,     // cap on any single interval
    jitter:      0.5,      // up to 50% random reduction (anti thundering-herd)
));

// Every verb helper inherits the policy transparently.
$response = $client->get('https://api.example.com/flaky');

Behaviour and backward-compatibility:

  • Default (no policy) = exactly one attempt — identical to previous releases.
  • A non-retryable 4xx/5xx response is still returned, never thrown (PSR-18).
  • A retryable response that exhausts the attempt cap is returned as-is (the last response); a transport exception that exhausts the cap is re-thrown.
  • A parseable Retry-After header (delay-seconds or HTTP-date) on a retryable response overrides the computed backoff unless you disable it.
  • The retryable status set, whether transport exceptions are retried, and Retry-After handling are all configurable on RetryPolicy.
// Customise: only retry 429/503, never on transport exceptions, ignore Retry-After.
new RetryPolicy(
    maxAttempts:          5,
    retryOnException:     false,
    retryableStatusCodes: [429, 503],
    respectRetryAfter:    false,
);

Emitting a response (SAPI)

use InitPHP\HTTP\Emitter\Emitter;

$emitter = new Emitter(/* strictMode: */ true);
$emitter->emit($response);                  // echoes body in one go

// For large bodies, stream in chunks:
$emitter->emit($response, 8192);

Range requests (Content-Range: bytes 0-1023/...) are honoured automatically.

Hydrating a ServerRequest from globals

use InitPHP\HTTP\Message\ServerRequest;

$request = ServerRequest::createFromGlobals();
// or with explicit data (recommended for tests and long-running runtimes):
$request = ServerRequest::createFromGlobals($server, $get, $post, $cookies, $files);

The factory is stateless — every call returns a fresh instance computed from the supplied arrays. Safe under Swoole, RoadRunner, Octane and FrankenPHP.

Using the static facades

For projects that prefer terseness over explicit DI:

use InitPHP\HTTP\Facade\Factory;
use InitPHP\HTTP\Facade\Client;
use InitPHP\HTTP\Facade\Emitter;

$request  = Factory::createRequest('GET', 'https://example.com');
$response = Client::sendRequest($request);
Emitter::emit($response);

Each facade lazily resolves a singleton on first call; subsequent calls return the same instance. Facades are entirely optional — every facade is just a thin static wrapper over a concrete service class you can instantiate yourself.

Documentation

In-depth guides live under docs/:

  • Getting Started
  • PSR-7 — Messages, ServerRequest, Streams, Uri, Uploaded Files
  • PSR-17 — Factory
  • PSR-18 — Client, Exceptions, Configuration
  • Emitter — Basics, Chunked bodies, Content-Range
  • Facades — Overview, Customisation
  • Recipes — JSON responses, Redirects, File uploads, Streaming large files, Proxying requests
  • HTTP status code reference
  • Upgrade guide (2.x → 3.x)

PSR Compliance

This package is verified against the official compliance suites:

Suite Result
php-http/psr7-integration-tests passing
http-interop/http-factory-tests (PSR-17) passing
In-house PSR-18 smoke suite against the PHP built-in test server passing
In-house PSR-7 immutability suite passing

Relevant specs: PSR-7, PSR-17, PSR-18.

Migration from 2.x

Version 3.0 is a breaking release. The highlights:

  • The custom InitPHP\HTTP\Message\Interfaces\* interfaces have been removed. Type-hint against the PSR-7 interfaces directly (Psr\Http\Message\RequestInterface, etc.).
  • Request::createFromGlobals() and the magic $request->name = $value parameter bag have been removed. Use ServerRequest::createFromGlobals() (now stateless) and $request->getParsedBody() instead.
  • Client::sendRequest() no longer inspects the concrete Request class — it only sees the PSR-7 contract. Pre-encode array/DOM/XML payloads before calling.
  • Client now defaults to a 30 s request timeout and 10 s connect timeout. Pass ->withTimeout(0) if you need the legacy "no timeout" behaviour.
  • The misspelled facade trait/interface names Facadeble[Interface] are now Facadable[Interface]; the old names remain as @deprecated aliases and will be removed in 4.0.

See docs/upgrade-guide.md for the full migration walk-through and a copy-pasteable code-mod list.

Contributing

Contributions are welcome — bug reports, doc improvements, performance patches, anything.

  • Open issues and pull requests against InitPHP/HTTP.

  • The project's organisation-wide Contributing Guide and Code of Conduct apply.

  • Local development:

    composer install
    composer ci        # phpstan + phpunit

Security

If you discover a security vulnerability please review the project's Security Policy and report it privately. Please do not file public GitHub issues for security problems.

License

MIT License — Copyright © Muhammet ŞAFAK and contributors.

About

Standards-compliant PSR-7, PSR-17, PSR-18 HTTP messages, factories, cURL client, and SAPI response emitter for PHP 7.4+ (PSR-7 v1 & v2 compatible).

initphp.org

Topics

curlhttphttp-clienthttp-emitterhttp-factoryhttp-messageimmutablephppsr-17psr-18psr-7requestresponsestreamuploaded-fileuri

Resources

Readme
MIT license

Code of conduct

Code of conduct

Contributing

Contributing

Security policy

Security policy
Activity
Custom properties

Stars

2 stars

Watchers

1 watching

Forks

0 forks
Report repository

Releases

Sponsor this project

Packages

Used by

Contributors

Languages

You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.