PHPackages                             initphp/http - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. initphp/http

ActiveLibrary[HTTP &amp; Networking](/categories/http)

initphp/http
============

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

3.1.0(1mo ago)22544MITPHPPHP &gt;=7.4CI passing

Since Mar 21Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/InitPHP/HTTP)[ Packagist](https://packagist.org/packages/initphp/http)[ Docs](https://github.com/InitPHP/HTTP)[ GitHub Sponsors](https://github.com/muhammetsafak)[ RSS](/packages/initphp-http/feed)WikiDiscussions main Synced yesterday

READMEChangelog (8)Dependencies (17)Versions (16)Used By (4)

InitPHP HTTP
============

[](#initphp-http)

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

[![Latest Stable Version](https://camo.githubusercontent.com/35183de282a2a9b5d08c52ecee4297122dc626b5d90e70a4b0f85cc4d64576c4/68747470733a2f2f706f7365722e707567782e6f72672f696e69747068702f687474702f76)](https://packagist.org/packages/initphp/http)[![Total Downloads](https://camo.githubusercontent.com/fc51fa09804f63da3454b529693a6d46b51182ab315da657b7d348962dd343e6/68747470733a2f2f706f7365722e707567782e6f72672f696e69747068702f687474702f646f776e6c6f616473)](https://packagist.org/packages/initphp/http)[![License](https://camo.githubusercontent.com/a2ead263a4ef8567ddf29fd1d1d47adb5c5e7e62a189cec4dc514700d00c897b/68747470733a2f2f706f7365722e707567782e6f72672f696e69747068702f687474702f6c6963656e7365)](https://packagist.org/packages/initphp/http)[![PHP Version Require](https://camo.githubusercontent.com/f63fd66bf8cbf1fa01d47db98def095d3327615e40354f915a24015f504ab00f/68747470733a2f2f706f7365722e707567782e6f72672f696e69747068702f687474702f726571756972652f706870)](https://packagist.org/packages/initphp/http)[![Tests](https://github.com/InitPHP/HTTP/actions/workflows/tests.yml/badge.svg)](https://github.com/InitPHP/HTTP/actions/workflows/tests.yml)[![Static Analysis](https://github.com/InitPHP/HTTP/actions/workflows/static-analysis.yml/badge.svg)](https://github.com/InitPHP/HTTP/actions/workflows/static-analysis.yml)

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
-----------------

[](#table-of-contents)

- [Features](#features)
- [Requirements](#requirements)
- [Installation](#installation)
- [Quick Start](#quick-start)
    - [Building a PSR-7 Request](#building-a-psr-7-request)
    - [Building a PSR-7 Response](#building-a-psr-7-response)
    - [Sending an HTTP request (PSR-18)](#sending-an-http-request-psr-18)
    - [Emitting a response (SAPI)](#emitting-a-response-sapi)
    - [Hydrating a ServerRequest from globals](#hydrating-a-serverrequest-from-globals)
    - [Using the static facades](#using-the-static-facades)
- [Documentation](#documentation)
- [PSR Compliance](#psr-compliance)
- [Migration from 2.x](#migration-from-2x)
- [Contributing](#contributing)
- [Security](#security)
- [License](#license)

---

Features
--------

[](#features)

- **PSR-7 v1 &amp; 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
------------

[](#requirements)

ComponentMinimumPHP7.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
------------

[](#installation)

```
composer require initphp/http
```

Quick Start
-----------

[](#quick-start)

### Building a PSR-7 Request

[](#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

[](#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)

[](#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

[](#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)

[](#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

[](#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

[](#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
-------------

[](#documentation)

In-depth guides live under [`docs/`](docs/):

- [Getting Started](docs/getting-started.md)
- PSR-7 — [Messages](docs/psr7/messages.md), [ServerRequest](docs/psr7/server-request.md), [Streams](docs/psr7/streams.md), [Uri](docs/psr7/uri.md), [Uploaded Files](docs/psr7/uploaded-files.md)
- PSR-17 — [Factory](docs/psr17/factory.md)
- PSR-18 — [Client](docs/psr18/client.md), [Exceptions](docs/psr18/exceptions.md), [Configuration](docs/psr18/configuration.md)
- Emitter — [Basics](docs/emitter/basic-emission.md), [Chunked bodies](docs/emitter/chunked-bodies.md), [Content-Range](docs/emitter/content-range.md)
- Facades — [Overview](docs/facades/overview.md), [Customisation](docs/facades/customization.md)
- Recipes — [JSON responses](docs/recipes/json-response.md), [Redirects](docs/recipes/redirect.md), [File uploads](docs/recipes/file-upload.md), [Streaming large files](docs/recipes/streaming-large-files.md), [Proxying requests](docs/recipes/proxying-requests.md)
- [HTTP status code reference](docs/reference/http-status-codes.md)
- [Upgrade guide (2.x → 3.x)](docs/upgrade-guide.md)

PSR Compliance
--------------

[](#psr-compliance)

This package is verified against the official compliance suites:

SuiteResult[`php-http/psr7-integration-tests`](https://github.com/php-http/psr7-integration-tests)passing[`http-interop/http-factory-tests`](https://github.com/http-interop/http-factory-tests) (PSR-17)passingIn-house PSR-18 smoke suite against the PHP built-in test serverpassingIn-house PSR-7 immutability suitepassingRelevant specs: [PSR-7](https://www.php-fig.org/psr/psr-7/), [PSR-17](https://www.php-fig.org/psr/psr-17/), [PSR-18](https://www.php-fig.org/psr/psr-18/).

Migration from 2.x
------------------

[](#migration-from-2x)

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`](docs/upgrade-guide.md) for the full migration walk-through and a copy-pasteable code-mod list.

Contributing
------------

[](#contributing)

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

- Open issues and pull requests against [InitPHP/HTTP](https://github.com/InitPHP/HTTP).
- The project's organisation-wide [Contributing Guide](https://github.com/InitPHP/.github/blob/main/CONTRIBUTING.md) and [Code of Conduct](https://github.com/InitPHP/.github/blob/main/CODE_OF_CONDUCT.md) apply.
- Local development:

    ```
    composer install
    composer ci        # phpstan + phpunit
    ```

Security
--------

[](#security)

If you discover a security vulnerability please review the project's [Security Policy](https://github.com/InitPHP/.github/blob/main/SECURITY.md) and report it privately. **Please do not file public GitHub issues for security problems.**

License
-------

[](#license)

[MIT License](./LICENSE) — Copyright © Muhammet ŞAFAK and contributors.

###  Health Score

45

—

FairBetter than 91% of packages

Maintenance88

Actively maintained with recent releases

Popularity14

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity57

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~111 days

Recently: every ~7 days

Total

15

Last Release

59d ago

Major Versions

1.0.3.x-dev → 2.0.x-dev2023-03-16

2.2.2 → 3.x-dev2026-05-24

### Community

Maintainers

![](https://www.gravatar.com/avatar/4b6b34f3ac8938d8ee52ba3bd260680855dc5715c7b2929d9380de30d15a67dd?d=identicon)[muhammetsafak](/maintainers/muhammetsafak)

---

Top Contributors

[![muhammetsafak](https://avatars.githubusercontent.com/u/104234499?v=4)](https://github.com/muhammetsafak "muhammetsafak (23 commits)")

---

Tags

curlhttphttp-clienthttp-emitterhttp-factoryhttp-messageimmutablephppsr-17psr-18psr-7requestresponsestreamuploaded-fileurihttpresponserequestpsr-7http-messagestreamuripsr-17curlhttp clientpsr-18emitterhttp-factoryuploaded filepsr-7-messagepsr-7-factorypsr-7-client

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/initphp-http/health.svg)

```
[![Health](https://phpackages.com/badges/initphp-http/health.svg)](https://phpackages.com/packages/initphp-http)
```

###  Alternatives

[guzzlehttp/psr7

PSR-7 message implementation that also provides common utility methods

7.9k1.1B4.4k](/packages/guzzlehttp-psr7)[tempest/framework

The PHP framework that gets out of your way.

2.3k37.6k21](/packages/tempest-framework)[art4/requests-psr18-adapter

Use WordPress/Requests as a PSR-18 HTTP client

159.3k](/packages/art4-requests-psr18-adapter)[flow-php/flow

PHP ETL - Extract Transform Load - Data processing framework

86337.5k](/packages/flow-php-flow)[telnyx/telnyx-php

Official Telnyx PHP SDK — APIs for Voice, SMS, MMS, WhatsApp, Fax, SIP Trunking, Wireless IoT, Call Control, and more. Build global communications on Telnyx's private carrier-grade network.

36826.2k2](/packages/telnyx-telnyx-php)[chillerlan/php-httpinterface

A PSR-7/17/18 http message/client implementation

1419.2k8](/packages/chillerlan-php-httpinterface)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
