PHPackages                             monkeyscloud/monkeyslegion-http-client - 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. monkeyscloud/monkeyslegion-http-client

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

monkeyscloud/monkeyslegion-http-client
======================================

Enterprise outbound HTTP client for MonkeysLegion: fluent API, cURL transport with connection pooling, middleware pipeline, retry/backoff, PSR-18 bridge, async pools.

1.0.0(3w ago)049↑83.7%2MITPHPPHP ^8.4

Since May 17Pushed 3w agoCompare

[ Source](https://github.com/MonkeysCloud/MonkeysLegion-HTTP-Client)[ Packagist](https://packagist.org/packages/monkeyscloud/monkeyslegion-http-client)[ RSS](/packages/monkeyscloud-monkeyslegion-http-client/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (8)Versions (2)Used By (2)

MonkeysLegion HTTP Client v1
============================

[](#monkeyslegion-http-client-v1)

Enterprise outbound HTTP client for MonkeysLegion: fluent API, cURL transport with connection pooling, middleware pipeline, retry/backoff, PSR-18 bridge, async pools. Zero external runtime dependencies — just `ext-curl` and PSR interfaces.

Features
--------

[](#features)

FeatureDescription**Fluent API**`$client->withToken($t)->post('/api', $data)`**cURL Transport**Connection pooling, keep-alive, TLS session reuse, LRU eviction**Middleware Pipeline**Retry, Auth, Logging, RateLimit, Timeout — composable chain**Retry with Backoff**Constant, linear, exponential, exponential+jitter strategies**PSR-18 Bridge**Bidirectional: use as PSR-18 client or wrap any PSR-18 as transport**Async Pool**Concurrent `curl_multi_*` requests with configurable concurrency**Mock Transport**Queued responses + request history for testing**Event System**RequestSending, ResponseReceived, RequestFailed, RetryAttempted**PHPStan Level 9**Full static analysis compliance, 0 errorsRequirements
------------

[](#requirements)

- **PHP 8.4+**
- **ext-curl**
- `psr/http-client` ^1.0
- `psr/http-message` ^2.0
- `psr/http-factory` ^1.1

Installation
------------

[](#installation)

```
composer require monkeyscloud/monkeyslegion-http-client
```

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

[](#quick-start)

```
use MonkeysLegion\HttpClient\HttpClient;
use MonkeysLegion\HttpClient\DTO\ClientConfig;

$client = new HttpClient(new ClientConfig(
    baseUrl: 'https://api.example.com',
    timeout: 15,
));

// GET with query params
$response = $client->get('/users', query: ['page' => '1', 'limit' => '25']);
$users = $response->json();

// POST with JSON body
$response = $client->post('/users', json: [
    'name'  => 'Jorge',
    'email' => 'jorge@monkeys.cloud',
]);

// Fluent builder
$response = $client
    ->withToken($apiToken)
    ->withHeader('X-Request-Id', uniqid())
    ->timeout(5)
    ->post('/orders', ['product_id' => 42, 'qty' => 1]);

// Response helpers
$response->statusCode;    // 201
$response->isOk;          // true
$response->json();        // ['id' => 1, 'name' => 'Jorge']
$response->get('id');     // 1
$response->header('X-RateLimit-Remaining'); // "42"
$response->duration;      // 0.234 (seconds)
```

Architecture
------------

[](#architecture)

```
┌──────────────────────────────────────────────────────┐
│                   HttpClient (fluent)                 │
└──────────────────────┬───────────────────────────────┘
                       ▼
┌──────────────────────────────────────────────────────┐
│              Middleware Pipeline                      │
│  Retry → RateLimit → Auth → Logging → Timeout → …  │
└──────────────────────┬───────────────────────────────┘
                       ▼
┌──────────────────────────────────────────────────────┐
│                Transport Layer                       │
│  ┌───────────┐  ┌──────────┐  ┌────────────────┐   │
│  │ CurlTransp│  │MockTransp│  │PsrTranspAdapter│   │
│  │ (pooled)  │  │(testing) │  │(Guzzle bridge) │   │
│  └───────────┘  └──────────┘  └────────────────┘   │
└──────────────────────────────────────────────────────┘

```

Middleware
----------

[](#middleware)

### Retry

[](#retry)

```
use MonkeysLegion\HttpClient\Middleware\RetryMiddleware;
use MonkeysLegion\HttpClient\Retry\RetryPolicy;
use MonkeysLegion\HttpClient\Enum\BackoffStrategy;
use MonkeysLegion\HttpClient\Pipeline\MiddlewarePipeline;
use MonkeysLegion\HttpClient\Transport\CurlTransport;

$transport = new MiddlewarePipeline(new CurlTransport());
$transport->pipe(new RetryMiddleware(new RetryPolicy(
    maxAttempts: 3,
    backoff: BackoffStrategy::ExponentialJitter,
    baseDelayMs: 100,
    maxDelayMs: 5000,
    retryableStatusCodes: [429, 500, 502, 503, 504],
)));

$client = new HttpClient(transport: $transport);
```

### Authentication

[](#authentication)

```
use MonkeysLegion\HttpClient\Middleware\AuthMiddleware;

// Bearer token
$transport->pipe(AuthMiddleware::bearer($token));

// Basic auth
$transport->pipe(AuthMiddleware::basic('user', 'pass'));

// API key header
$transport->pipe(AuthMiddleware::apiKey('sk_live_xxx', 'X-API-Key'));

// Custom callback
$transport->pipe(AuthMiddleware::custom(fn($req) =>
    $req->withHeaders(['X-Signature' => hmac($req->body)])
));
```

### Logging (PSR-3)

[](#logging-psr-3)

```
use MonkeysLegion\HttpClient\Middleware\LoggingMiddleware;

$transport->pipe(new LoggingMiddleware(
    logger: $psrLogger,
    level: 'debug',
    bodyLimit: 1024, // truncate bodies > 1KB
));
// Automatically redacts Authorization, Cookie, X-API-Key headers
```

### Rate Limiting

[](#rate-limiting)

```
use MonkeysLegion\HttpClient\Middleware\RateLimitMiddleware;

$transport->pipe(new RateLimitMiddleware(maxPerSecond: 10));
// Per-domain token bucket
```

### Timeout

[](#timeout)

```
use MonkeysLegion\HttpClient\Middleware\TimeoutMiddleware;

$transport->pipe(new TimeoutMiddleware(timeout: 30, connectTimeout: 5));
```

PSR-18 Bridge
-------------

[](#psr-18-bridge)

### Use HttpClient as PSR-18

[](#use-httpclient-as-psr-18)

```
use MonkeysLegion\HttpClient\Bridge\PsrClientAdapter;

$psrClient = new PsrClientAdapter($httpClient);
$psrResponse = $psrClient->sendRequest($psrRequest);
// Works as drop-in for any PSR-18 consumer (Stripe, AWS SDK, etc.)
```

### Use Guzzle as Transport

[](#use-guzzle-as-transport)

```
use MonkeysLegion\HttpClient\Bridge\PsrTransportAdapter;
use GuzzleHttp\Client as GuzzleClient;
use GuzzleHttp\Psr7\HttpFactory;

$guzzle = new GuzzleClient();
$factory = new HttpFactory();
$transport = new PsrTransportAdapter($guzzle, $factory, $factory);

$client = new HttpClient(transport: $transport);
```

Async / Concurrent Requests
---------------------------

[](#async--concurrent-requests)

```
use MonkeysLegion\HttpClient\Async\Pool;
use MonkeysLegion\HttpClient\DTO\RequestContext;
use MonkeysLegion\HttpClient\Enum\HttpMethod;

$requests = [
    new RequestContext(HttpMethod::GET, 'https://api.example.com/users/1'),
    new RequestContext(HttpMethod::GET, 'https://api.example.com/users/2'),
    new RequestContext(HttpMethod::GET, 'https://api.example.com/users/3'),
];

$responses = Pool::send($transport, $requests, concurrency: 5);
// Returns list in same order as requests
```

Testing
-------

[](#testing)

```
use MonkeysLegion\HttpClient\Transport\MockTransport;
use MonkeysLegion\HttpClient\HttpClient;

$mock = new MockTransport();
$mock->enqueueJson(['id' => 1, 'name' => 'Test'], statusCode: 201);

$client = new HttpClient(transport: $mock);
$response = $client->post('/users', json: ['name' => 'Test']);

assert($response->statusCode === 201);
assert($response->get('name') === 'Test');
assert($mock->requestCount() === 1);
assert($mock->assertSent('/users'));
```

Configuration
-------------

[](#configuration)

```
php ml http-client:install
```

```
http_client {
    timeout         = ${HTTP_CLIENT_TIMEOUT:-30}
    connect_timeout = ${HTTP_CLIENT_CONNECT_TIMEOUT:-5}
    verify_ssl      = ${HTTP_CLIENT_VERIFY_SSL:-true}
    max_redirects   = ${HTTP_CLIENT_MAX_REDIRECTS:-5}
    user_agent      = ${HTTP_CLIENT_USER_AGENT:-MonkeysLegion/2.0}
    pool_size       = ${HTTP_CLIENT_POOL_SIZE:-10}
    throw_on_error  = ${HTTP_CLIENT_THROW_ON_ERROR:-false}

    retry {
        max_attempts = ${HTTP_CLIENT_RETRY_MAX:-3}
        backoff      = ${HTTP_CLIENT_RETRY_BACKOFF:-exponential_jitter}
        base_delay   = ${HTTP_CLIENT_RETRY_DELAY:-100}
        max_delay    = ${HTTP_CLIENT_RETRY_MAX_DELAY:-5000}
    }
}

```

Events
------

[](#events)

EventWhen`RequestSending`Before request is sent`ResponseReceived`After response received`RequestFailed`On connection/timeout failure`RetryAttempted`When retry is triggeredResponse API
------------

[](#response-api)

```
$response->statusCode;     // int
$response->body;           // string (raw)
$response->headers;        // array
$response->duration;       // float (seconds)
$response->isOk;           // 2xx
$response->isRedirect;     // 3xx
$response->isClientError;  // 4xx
$response->isServerError;  // 5xx
$response->isFailed;       // 4xx or 5xx
$response->json();         // array
$response->get('key');     // dot-notation access
$response->header('name'); // case-insensitive header lookup
$response->toArray();      // full response as array
```

License
-------

[](#license)

MIT © [MonkeysCloud](https://monkeys.cloud)

###  Health Score

44

—

FairBetter than 90% of packages

Maintenance95

Actively maintained with recent releases

Popularity12

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity51

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

Unknown

Total

1

Last Release

24d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/2913369?v=4)[Jorge Peraza](/maintainers/yorchperaza)[@yorchperaza](https://github.com/yorchperaza)

---

Top Contributors

[![yorchperaza](https://avatars.githubusercontent.com/u/2913369?v=4)](https://github.com/yorchperaza "yorchperaza (1 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/monkeyscloud-monkeyslegion-http-client/health.svg)

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

###  Alternatives

[guzzlehttp/psr7

PSR-7 message implementation that also provides common utility methods

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

The PHP framework that gets out of your way.

2.2k31.1k11](/packages/tempest-framework)[cakephp/cakephp

The CakePHP framework

8.8k19.1M1.7k](/packages/cakephp-cakephp)[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.

35729.6k2](/packages/telnyx-telnyx-php)[flow-php/flow

PHP ETL - Extract Transform Load - Data processing framework

84735.1k](/packages/flow-php-flow)[laudis/neo4j-php-client

Neo4j-PHP-Client is the most advanced PHP Client for Neo4j

185671.3k41](/packages/laudis-neo4j-php-client)

PHPackages © 2026

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