Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

◐ Orbit

A self-healing proxy pool for PHP

Proxies die. Orbit routes around them. Rotation, async health checks, latency scoring and exponential-backoff cooldown — so a dead endpoint costs you one retry, not your whole run.

rotation strategies · async curl_multi checks · latency scoring · cooldown + ban · zero dependencies

⋆ ˚ 。 ⋆ ୨ ⋆ ˚ 。 ⋆

PHP License tests Zero deps Author


Why Orbit · Install · Quick start · Rotation · Health checks · Failure handling · With PulsarX · API


◈ Features

Feature What it does
Rotation Round-robin, random, or least-latency — swap strategy in one call.
Async checks Probe the whole list in parallel over curl_multi, with a rolling concurrency window.
Latency scoring Every success updates an EWMA latency score; least-latency routing uses it.
Self-healing Failures trigger exponential-backoff cooldown; repeat offenders get banned.
Formats HTTP/HTTPS and SOCKS4/4a/5/5h, with or without credentials, parsed from plain strings.
Testable Health checking is behind a ProberInterface — inject a fake and drive the pool deterministically.
Zero deps One class per file, a tiny autoloader, optional Composer.

◐ Why Orbit?

PHP's proxy landscape is all checkers — libraries that validate a list once and hand it back. None of them manage a live pool: rotating across it, scoring it by latency, and quarantining endpoints that start failing mid-run. Orbit is the stateful layer on top — the piece you actually wire into a scraper.

Orbit retrowaver/proxy-checker ilmlv/proxy-scraper roll-your-own
Validate proxies maybe
Rotation strategies ✓ 3
Latency scoring ✓ EWMA
Cooldown + ban on failure
Async (curl_multi) partial
PulsarX / cURL adapters
Runtime dependencies none none Guzzle

⬡ Installation

With Composer

composer require vxsilisk/orbit

Without Composer — require the bundled autoloader:

require __DIR__ . '/autoload.php';

Requirements: PHP ≥ 8.1. ext-curl only for the built-in health checker.


✷ Quick start

require __DIR__ . '/autoload.php';

$pool = Pool::fromList([
    '203.0.113.1:8080',
    'user:pass@203.0.113.2:3128',
    'socks5://203.0.113.3:1080',
])->strategy(Strategy::LeastLatency);

$pool->check();                          // probe all, score latency (async)

$proxy = $pool->next();                  // best available proxy
$ok = doRequestThrough($proxy);          // ... your request ...
$pool->report($proxy, $ok, $latency);    // feed the outcome back

Proxies parse from host:port, user:pass@host:port, or a full scheme://… URL. Scheme defaults to http.


◐ Rotation strategies

$pool->strategy(Strategy::RoundRobin);    // cycle in order (default)
$pool->strategy(Strategy::Random);        // uniformly random
$pool->strategy(Strategy::LeastLatency);  // fastest measured proxy first

Every strategy only ever returns a proxy that's available — not banned, not cooling down. When the pool is dry, next() throws OrbitException; use tryNext() for a null-returning variant.

while ($proxy = $pool->tryNext()) {
    // ... until everything is exhausted
}

⟡ Health checks

check() probes every proxy in parallel and folds the results back in as success/failure — updating latency scores and cooling down the dead ones:

$summary = $pool->check('https://httpbin.org/ip', timeout: 8, concurrency: 20);
// ['checked' => 50, 'alive' => 43, 'dead' => 7]

$pool->available();   // Proxy[] ready to use now
$pool->banned();      // Proxy[] struck out
$pool->stats();       // ['total'=>50, 'available'=>43, 'cooling_down'=>4, 'banned'=>3, 'avg_latency'=>0.31, ...]

The checker lives behind an interface, so tests (and exotic transports) can supply their own:

class MyProber implements ProberInterface { /* return [id => ['ok'=>bool,'latency'=>?float]] */ }

$pool->check(prober: new MyProber());

↻ Failure handling

Report a failure and Orbit sidelines the proxy with exponential backoff; after banThreshold consecutive strikes it's banned outright. A single success resets the counter.

$pool = new Pool(
    strategy: Strategy::RoundRobin,
    banThreshold: 5,      // ban after 5 straight failures
    baseCooldown: 2.0,    // first cooldown, seconds
    maxCooldown: 300.0,   // cap
);

$pool->report($proxy, false);   // 2s, then 4s, 8s, 16s … cooldown
$pool->report($proxy, true);    // recovered — counter back to zero
$pool->revive($proxy);          // manually lift a ban / cooldown

⇄ With PulsarX

Orbit is the scale layer of the PulsarX stack — hand each request a healthy proxy and report the result straight back:

$s = new Pulsar();

foreach ($urls as $url) {
    $proxy = $pool->next();
    $r = $s->get($url, server: $proxy->forPulsar());
    $pool->report($proxy, $r->ok(), $r->getElapsed());
}

forPulsar() returns exactly the server: array PulsarX expects; curlOptions() does the same for a raw cURL handle.


❯ API reference

Pool

Method Returns
Pool::fromList(array) / fromFile(string) Pool
add($proxy) / addMany(array) self
strategy(Strategy) self
next() / tryNext() Proxy / ?Proxy
report($proxy, bool $ok, ?float $latency) void
revive($proxy) void
check($url, $timeout, $concurrency, ?$prober) array{checked,alive,dead}
available() / banned() / all() Proxy[]
count() / stats() int / array

Proxy

Method Returns
Proxy::parse(string) Proxy
id() / url() string
hasAuth() / isAvailable(?float $now) bool
curlOptions() / forPulsar() / toArray() array
public state latency, failures, successes, banned, cooldownUntil, lastCheck

StrategyRoundRobin · Random · LeastLatency


❏ Project layout

Orbit/
├── autoload.php          # zero-dependency autoloader
├── composer.json
├── example.php           # runnable demo (no network needed)
├── tests/run.php         # framework-free test suite (fake prober + injected clock)
└── src/
    ├── Pool.php              # rotation · cooldown · banning · scoring · checks
    ├── Proxy.php             # one endpoint + its health state
    ├── Strategy.php          # RoundRobin | Random | LeastLatency
    ├── ProberInterface.php   # health-check contract
    ├── CurlProber.php        # default async curl_multi prober
    └── OrbitException.php

Run php example.php for a live demo, or php tests/run.php for the test suite.


⋆ ˚ 。 ⋆ ୨ ⋆ ˚ 。 ⋆

Orbit — made by Vxsilisk · MIT License

Part of the Nebula toolkit: PulsarX (fetch) · Quasar (parse) · Photon (identity) · Orbit (scale)

About

Self-healing proxy pool for PHP — rotation strategies, async curl_multi health checks, latency scoring, exponential-backoff cooldown and banning. Zero dependencies.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages