aurynx/http-compression
Composer 安装命令:
composer require aurynx/http-compression
包简介
Framework-agnostic HTTP compression for PHP (gzip, brotli, zstd) with deterministic builds and safe file precompression.
关键字:
README 文档
README
Modern PHP library for HTTP compression with native type safety
gzip • brotli • zstd — simple, safe, and fast
Installation • Quick Start • Features • Use Cases • API • Advanced Usage • AI Guide
Why HttpCompression?
Modern web applications need efficient compression to reduce bandwidth and improve response times. HttpCompression makes it simple with a clean, modern API focused on:
- 🔷 Native PHP 8.4+ types — zero docblock types, full IDE autocomplete
- 🎯 Single facade pattern — one intuitive API for all scenarios
- 🚀 Glob pattern support — compress entire directories with wildcards
- 💾 Memory-safe streaming — handle large files without memory limits
- 🛡️ Fail-fast validation — catch errors at configuration time
- 🤖 AI-friendly design — perfect for code generation and assistants
Installation
Requirements:
- PHP 8.4 or higher
ext-zlib(required for gzip)ext-brotli(optional, for brotli compression)ext-zstd(optional, for zstd compression)
composer require aurynx/http-compression
Quick Start
Single File Compression
use Aurynx\HttpCompression\CompressorFacade; use Aurynx\HttpCompression\Enums\AlgorithmEnum; // Compress and save to file CompressorFacade::once() ->file('public/index.html') ->withGzip(9) ->saveTo('public/index.html.gz'); // Compress in-memory data $html = '<html><body>Hello World</body></html>'; $result = CompressorFacade::once() ->data($html) ->withBrotli(11) ->compress(); $compressed = $result->getData(AlgorithmEnum::Brotli);
Batch Compression
use Aurynx\HttpCompression\CompressorFacade; use Aurynx\HttpCompression\ValueObjects\ItemConfig; $result = CompressorFacade::make() ->addGlob('public/**/*.{html,css,js}') ->withDefaultConfig( ItemConfig::create() ->withGzip(9) ->withBrotli(11) ->build() ) ->skipAlreadyCompressed() ->toDir('./dist') ->compress(); echo "Compressed {$result->count()} files\n"; echo "Success rate: " . ($result->allOk() ? '100%' : 'partial') . "\n";
Features
✨ Native Type Safety
The public API uses native PHP 8.4+ types everywhere (parameters, return types, readonly DTOs). This makes the library:
- Easier for IDEs and AI agents to navigate (no docblock type guessing)
- Safer at runtime thanks to engine-level type checks
- More self-documenting due to explicit signatures
Example signature:
public function compress(ItemConfig $config): CompressionResult
🎯 Fluent Facade API
Two facades for different scenarios:
CompressorFacade::make() — Batch compression
CompressorFacade::make() ->addFile('index.html') ->addGlob('assets/*.css') ->withDefaultConfig(ItemConfig::create()->withGzip(9)->build()) ->toDir('./output') ->compress();
CompressorFacade::once() — Quick single-item tasks
CompressorFacade::once() ->file('logo.svg') ->withGzip(9) ->saveTo('logo.svg.gz');
🚀 Glob Pattern Support
Compress entire directories with powerful glob patterns:
CompressorFacade::make() ->addGlob('public/**/*.html') // All HTML files recursively ->addGlob('assets/*.{css,js}') // CSS and JS in assets/ ->addGlob('fonts/*.woff2') // Specific extension ->skipAlreadyCompressed() // Skip images, videos, etc. ->toDir('./dist', keepStructure: true) ->compress();
💾 Memory-Safe Streaming
Handle large files without loading into memory:
use Aurynx\HttpCompression\ValueObjects\OutputConfig; $result = CompressorFacade::make() ->addFile('large-file.json') // 500MB file ->withDefaultConfig(ItemConfig::create()->withGzip(6)->build()) ->inMemory(maxBytes: 100_000_000) // 100MB limit ->compress(); // Stream compressed data $result->first()->read(AlgorithmEnum::Gzip, function (string $chunk) { echo $chunk; // Process in chunks });
🔌 Callback Streaming (no resources)
Stream compressed data directly into callbacks without dealing with stream resources.
Single algorithm (sendToCallback):
use Aurynx\HttpCompression\CompressorFacade; $buffer = ''; CompressorFacade::once() ->data(str_repeat('hello ', 5000)) ->withGzip(6) ->sendToCallback(function (string $chunk) use (&$buffer): void { $buffer .= $chunk; // write to socket, PSR-7 body, etc. });
Multiple algorithms (sendAllToCallbacks):
use Aurynx\HttpCompression\CompressorFacade; $gz = ''; CompressorFacade::once() ->data('payload') ->withGzip(6) // required by default ->tryBrotli(4) // optional ->sendAllToCallbacks([ 'gzip' => static function (string $chunk) use (&$gz): void { $gz .= $chunk; }, // 'br' may be omitted when added via tryBrotli() ]);
See more patterns and caveats in Advanced Usage:
- Callback streaming (single/multi)
- Low-level WritableStream wrapper
👉 Read: ./docs/advanced-usage.md
🛡️ Fail-Fast Validation
Errors are caught at configuration time, not during compression:
// ❌ Throws immediately (invalid level) AlgorithmSet::gzip(99); // InvalidArgumentException: Level must be between 1 and 9 // ❌ Throws immediately (multiple algorithms for saveTo) CompressorFacade::once() ->file('test.txt') ->withGzip(9) ->withBrotli(11) // Multiple algorithms ->saveTo('test.gz'); // CompressionException: saveTo() requires exactly one algorithm
📈 Rich Result Objects
Detailed statistics and easy access:
$result = CompressorFacade::make() ->addGlob('*.html') ->withDefaultConfig(ItemConfig::create()->withGzip(9)->withBrotli(11)->build()) ->inMemory() ->compress(); // Access results foreach ($result as $id => $item) { if ($item->isOk()) { echo "Original: {$item->originalSize} bytes\n"; echo "Gzip: {$item->compressedSizes['gzip']} bytes\n"; echo "Brotli: {$item->compressedSizes['brotli']} bytes\n"; } } // Aggregated statistics $summary = $result->summary(); echo "Median compression ratio (gzip): " . $summary->getMedianRatio(AlgorithmEnum::Gzip) . "\n"; echo "P95 compression time (brotli): " . $summary->getP95TimeMs(AlgorithmEnum::Brotli) . " ms\n";
Use Cases
1. Static Site Pre-Compression
Compress assets during build for nginx gzip_static:
use Aurynx\HttpCompression\CompressorFacade; use Aurynx\HttpCompression\ValueObjects\ItemConfig; // Build script $result = CompressorFacade::make() ->addGlob('dist/**/*.{html,css,js,svg,json}') ->withDefaultConfig( ItemConfig::create() ->withGzip(9) ->withBrotli(11) ->build() ) ->skipAlreadyCompressed() ->toDir('./dist', keepStructure: true) ->compress(); if (!$result->allOk()) { foreach ($result->failures() as $id => $failure) { echo "Failed: {$id} - {$failure->getFailureReason()?->getMessage()}\n"; } exit(1); } echo "✓ Compressed {$result->count()} files\n";
Nginx configuration:
gzip_static on; brotli_static on;
2. Dynamic HTTP Response Compression
Compress content on-the-fly with caching:
use Aurynx\HttpCompression\CompressorFacade; use Aurynx\HttpCompression\AlgorithmEnum; function compressResponse(string $content, string $acceptEncoding): string { $cacheKey = 'compressed_' . md5($content) . '_' . $acceptEncoding; if ($cached = apcu_fetch($cacheKey)) { return $cached; } $algo = str_contains($acceptEncoding, 'br') ? AlgorithmEnum::Brotli : AlgorithmEnum::Gzip; $result = CompressorFacade::once() ->data($content) ->withAlgorithm($algo, $algo->getDefaultLevel()) ->compress(); $compressed = $result->getData($algo); apcu_store($cacheKey, $compressed, 3600); return $compressed; } // In your controller $html = view('welcome')->render(); $acceptEncoding = $_SERVER['HTTP_ACCEPT_ENCODING'] ?? ''; if (str_contains($acceptEncoding, 'br') || str_contains($acceptEncoding, 'gzip')) { $compressed = compressResponse($html, $acceptEncoding); header('Content-Encoding: ' . (str_contains($acceptEncoding, 'br') ? 'br' : 'gzip')); echo $compressed; } else { echo $html; }
3. API Response Compression
Compress JSON API responses:
use Aurynx\HttpCompression\CompressorFacade; use Aurynx\HttpCompression\AlgorithmEnum; function compressApiResponse(array $data, string $acceptEncoding): string { $json = json_encode($data); if (!str_contains($acceptEncoding, 'gzip')) { return $json; } $result = CompressorFacade::once() ->data($json) ->withGzip(6) // Lower level for speed ->compress(); header('Content-Encoding: gzip'); header('Vary: Accept-Encoding'); return $result->getData(AlgorithmEnum::Gzip); } // Usage $data = ['users' => User::all()]; echo compressApiResponse($data, $_SERVER['HTTP_ACCEPT_ENCODING'] ?? '');
4. Log File Archival
Compress and archive old log files:
use Aurynx\HttpCompression\CompressorFacade; use Aurynx\HttpCompression\ValueObjects\ItemConfig; // Daily cron job $result = CompressorFacade::make() ->addGlob('storage/logs/*.log') ->withDefaultConfig(ItemConfig::create()->withZstd(19)->build()) // Maximum compression ->toDir('storage/logs/archive', keepStructure: false) ->compress(); // Delete originals foreach ($result->successes() as $id => $item) { $originalPath = "storage/logs/{$id}"; if (file_exists($originalPath)) { unlink($originalPath); } } echo "Archived {$result->count()} log files\n";
5. Asset Pipeline Integration
Integrate with your build tools:
use Aurynx\HttpCompression\CompressorFacade; use Aurynx\HttpCompression\ValueObjects\ItemConfig; class AssetCompiler { public function compile(): void { // Step 1: Bundle and minify (webpack, vite, etc.) system('npm run build'); // Step 2: Compress for production $result = CompressorFacade::make() ->addGlob('public/build/**/*.{js,css}') ->addGlob('public/build/**/*.{svg,json}') ->withDefaultConfig( ItemConfig::create() ->withGzip(9) ->withBrotli(11) ->build() ) ->skipExtensions(['woff2', 'png', 'jpg']) ->toDir('public/build', keepStructure: true) ->failFast(true) ->compress(); if (!$result->allOk()) { throw new \RuntimeException('Asset compression failed'); } $summary = $result->summary(); $avgRatio = $summary->getAverageRatio(AlgorithmEnum::Gzip); echo "✓ Compressed {$result->count()} assets (avg ratio: " . round($avgRatio * 100, 1) . "%)\n"; } }
API Reference
Facades
CompressorFacade::make() — Batch Compression
use Aurynx\HttpCompression\CompressorFacade; $result = CompressorFacade::make() // Add inputs ->add(CompressionInput $input, ?ItemConfig $config = null) ->addMany(iterable $inputs) ->addFile(string $path, ?ItemConfig $config = null, ?string $id = null) ->addData(string $data, ?ItemConfig $config = null, ?string $id = null) ->addGlob(string $pattern, ?ItemConfig $config = null) ->addFrom(InputProviderInterface $provider, ?ItemConfig $config = null) // Configuration ->withDefaultConfig(ItemConfig $config) // Output ->toDir(string $dir, bool $keepStructure = false) ->inMemory(int $maxBytes = 5_000_000) // Options ->failFast(bool $enable = true) ->skipExtensions(array $extensions) ->skipAlreadyCompressed() // Execute ->compress(): CompressionResult;
CompressorFacade::once() — Single Item
use Aurynx\HttpCompression\CompressorFacade; CompressorFacade::once() // Input ->file(string $path) ->data(string $data) // Algorithm (choose ONE) ->withGzip(int $level = 6) ->withBrotli(int $level = 11) ->withZstd(int $level = 3) // Execute ->compress(): CompressionItemResult ->saveTo(string $path): void; // Requires exactly one algorithm
Notes on Saving Files
-
saveTo(path):
- Atomic write (tmp + rename) to the target path
- Existing target is replaced (OverwritePolicy=Replace)
- The target directory must already exist (no auto-create)
-
saveAllTo(directory, basename, options):
- basename must be a plain filename (no '/' or '\', not '.' or '..')
- Options:
- overwritePolicy: fail|replace|skip (default fail)
- atomicAll: bool (default true) — all-or-nothing semantics
- allowCreateDirs: bool (default true)
- permissions: int|null — chmod after successful rename
Configuration
ItemConfig — Compression Configuration
use Aurynx\HttpCompression\ValueObjects\ItemConfig; use Aurynx\HttpCompression\ValueObjects\AlgorithmSet; // Using builder $config = ItemConfig::create() ->withGzip(9) ->withBrotli(11) ->withZstd(3) ->limitBytes(5_000_000) ->build(); // Direct instantiation $config = new ItemConfig( algorithms: AlgorithmSet::gzip(9), maxBytes: 1_000_000 ); // Static factories $config = ItemConfig::gzip(9); $config = ItemConfig::brotli(11); $config = ItemConfig::zstd(3);
AlgorithmSet — Algorithm Configuration
use Aurynx\HttpCompression\ValueObjects\AlgorithmSet; use Aurynx\HttpCompression\Enums\AlgorithmEnum; // Static factories $set = AlgorithmSet::gzip(9); $set = AlgorithmSet::brotli(11); $set = AlgorithmSet::zstd(3); $set = AlgorithmSet::fromDefaults(); // All algorithms with default levels // Manual construction from pairs $set = AlgorithmSet::from([ [AlgorithmEnum::Gzip, 9], [AlgorithmEnum::Brotli, 11], ]);
Results
CompressionResult — Batch Results
$result = CompressorFacade::make()->compress(); // Access $result->get(string $id): CompressionItemResult $result->first(): CompressionItemResult $result->toArray(): array // Filtering $result->successes(): array $result->failures(): array $result->allOk(): bool // Statistics $result->summary(): CompressionSummaryResult $result->count(): int // Iteration foreach ($result as $id => $item) { // Process each item }
CompressionItemResult — Single Item Result
$item = $result->first(); // Status $item->isOk(): bool $item->success: bool $item->originalSize: int // Data access $item->getData(AlgorithmEnum $algo): string $item->getStream(AlgorithmEnum $algo): resource $item->read(AlgorithmEnum $algo, callable $consumer): void // Metadata $item->has(AlgorithmEnum $algo): bool $item->compressedSizes: array<string, int> $item->compressionTimes: array<string, float> $item->errors: array<string, \Throwable> $item->getFailureReason(): ?\Throwable
CompressionSummaryResult — Aggregated Statistics
$summary = $result->summary(); // Compression ratios (compressed / original) $summary->getAverageRatio(AlgorithmEnum $algo): float $summary->getMedianRatio(AlgorithmEnum $algo): float // p50 $summary->getP95Ratio(AlgorithmEnum $algo): float // Timing (milliseconds) $summary->getMedianTimeMs(AlgorithmEnum $algo): float // p50 $summary->getP95TimeMs(AlgorithmEnum $algo): float $summary->getTotalTimeMs(AlgorithmEnum $algo): float // Counts $summary->getTotalItems(): int $summary->getSuccessCount(): int $summary->getFailureCount(): int
For AI Assistants
This library is designed to be AI-friendly with:
- ✅ Native types — no docblock parsing needed
- ✅ Explicit naming —
CompressionResult,AlgorithmEnum, etc. - ✅ Fluent API — easy to chain methods
- ✅ Fail-fast — errors are obvious and immediate
- ✅ Immutable value objects — no side effects
For a deeper, agent-focused walkthrough, see the AI Guide: AI_GUIDE.md. You can also use the machine-readable schema docs/ai-manifest.json.
Common Patterns
// Quick compression CompressorFacade::once()->file('test.txt')->withGzip(9)->saveTo('test.txt.gz'); // Batch with glob CompressorFacade::make() ->addGlob('*.html') ->withDefaultConfig(ItemConfig::create()->withGzip(9)->build()) ->toDir('./out') ->compress(); // Multiple algorithms $config = ItemConfig::create() ->withGzip(9) ->withBrotli(11) ->withZstd(3) ->build();
Avoid These Mistakes
❌ Multiple algorithms with saveTo():
// WRONG - saveTo() requires exactly one algorithm CompressorFacade::once()->file('x')->withGzip()->withBrotli()->saveTo('x.gz');
✅ Use compress() instead:
$result = CompressorFacade::once()->file('x')->withGzip()->withBrotli()->compress(); $result->getData(AlgorithmEnum::Gzip);
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for details.
Development Setup
# Install dependencies composer install # Run tests composer test # Run PHPStan composer phpstan # Run CS Fixer composer cs-fix
License
The MIT License (MIT). Please see License File for more information.
Credits
Created and maintained by Anton Semenov.
Crafted by Aurynx 🔮
aurynx/http-compression 适用场景与选型建议
aurynx/http-compression 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 4 次下载、GitHub Stars 达 0, 最近一次更新时间为 2025 年 10 月 10 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「php」 「http」 「compression」 「compressor」 「static」 「nginx」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 aurynx/http-compression 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 aurynx/http-compression 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 aurynx/http-compression 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Asset Management for PHP
repository php library
Image optimization / compression library. This library is able to optimize png, jpg and gif files in very easy and handy way. It uses optipng, pngquant, pngcrush, pngout, gifsicle, jpegoptim and jpegtran tools.
Yii2 integration for TinyPng
Smart compressed files extractor
http客户端
统计信息
- 总下载量: 4
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 31
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2025-10-10