TCP proxy и HTTP gateway
В src/Proxy и src/Gateway есть два отдельных компонента. Оба подключаются к raw TCP Server без application protocol; gateway сам обрабатывает только HTTP/1.x framing.
Общий пул upstream
UpstreamPool поддерживает weighted round-robin, least-connections и random selection, пассивное quarantine после ошибок и восстановление после успешной проверки соединения.
use localzet\Server\Gateway\HttpReverseProxy;
use localzet\Server\Gateway\HttpRoute;
use localzet\Server\Proxy\UpstreamPool;
$pool = new UpstreamPool(
['tcp://10.0.0.10:8080', 'tcp://10.0.0.11:8080'],
UpstreamPool::ROUND_ROBIN,
failureThreshold: 2,
quarantineSeconds: 5.0,
);
UpstreamPool принимает TCP URI, например tcp://host:port; URI и адреса upstream задаются конфигурацией приложения.
HTTP/1.x reverse proxy
use localzet\Server;
use localzet\Server\Gateway\HttpReverseProxy;
use localzet\Server\Gateway\HttpRoute;
$gateway = (new HttpReverseProxy())
->setConnectTimeout(2.0)
->setMaxHeaderSize(32 * 1024)
->route(new HttpRoute(
pool: $pool,
host: 'api.example.test',
pathPrefix: '/api/',
rewritePrefix: '/v1/',
));
$server = new Server('tcp://0.0.0.0:8080');
$gateway->attach($server);
Server::runAll();
Маршрут сопоставляет Host и prefix пути. Поддерживаются streaming request/response body, Content-Length, chunked transfer, keep-alive и WebSocket Upgrade tunneling. Gateway обрабатывает один in-flight запрос на клиентское соединение: pipelined bytes буферизуются, следующий запрос отправляется после ответа.
Повторное подключение к другому upstream допускается до установления соединения. После connect автоматического повторного воспроизведения запроса нет: upstream мог уже обработать часть данных. В status() доступны runtime counters текущего worker-а; это не централизованный metrics exporter.
Raw TCP proxy
use localzet\Server;
use localzet\Server\Proxy\TcpProxy;
$proxy = new TcpProxy($pool, connectTimeout: 2.0);
$server = new Server('tcp://0.0.0.0:9000');
$proxy->attach($server);
Server::runAll();
TCP proxy передаёт bytes как есть и использует backpressure. Listener должен оставаться raw TCP, без другого Server::$protocol.
Границы и безопасность
Здесь нет HTTP/2/3, TLS termination management, cache, service discovery, circuit-breaker API, rate limiter или access-control policy. Используйте фиксированный allowlist upstream-ов; не строите upstream URI из пользовательского запроса. Ограничьте доступ к listener-у сетевыми правилами и настройте timeout/лимит соединений на приложении и edge proxy.

