Files
portal-api/app/Http/Middleware/CompressionMiddleware.php
T

90 lines
2.8 KiB
PHP

<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class CompressionMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
* @return \Symfony\Component\HttpFoundation\Response
*/
public function handle(Request $request, Closure $next): Response
{
$response = $next($request);
// Chỉ nén response cho JSON API
if (!$this->shouldCompress($request, $response)) {
return $response;
}
$content = $response->getContent();
// Chỉ nén nếu content size > 1KB
if (strlen($content) < 1024) {
return $response;
}
$acceptEncoding = $request->header('Accept-Encoding', '');
// Kiểm tra client hỗ trợ gzip
if (str_contains($acceptEncoding, 'gzip') && function_exists('gzencode')) {
$compressed = gzencode($content, 6); // Level 6 compression
if ($compressed !== false) {
$response->setContent($compressed);
$response->headers->set('Content-Encoding', 'gzip');
$response->headers->set('Content-Length', strlen($compressed));
$response->headers->set('Vary', 'Accept-Encoding');
}
}
// Fallback to deflate if gzip not supported
elseif (str_contains($acceptEncoding, 'deflate') && function_exists('gzdeflate')) {
$compressed = gzdeflate($content, 6);
if ($compressed !== false) {
$response->setContent($compressed);
$response->headers->set('Content-Encoding', 'deflate');
$response->headers->set('Content-Length', strlen($compressed));
$response->headers->set('Vary', 'Accept-Encoding');
}
}
return $response;
}
/**
* Determine if the response should be compressed.
*/
private function shouldCompress(Request $request, Response $response): bool
{
// Chỉ nén JSON responses
$contentType = $response->headers->get('Content-Type', '');
if (!str_contains($contentType, 'application/json')) {
return false;
}
// Không nén nếu đã có Content-Encoding
if ($response->headers->has('Content-Encoding')) {
return false;
}
// Không nén file downloads
if ($response->headers->has('Content-Disposition')) {
return false;
}
// Chỉ nén response thành công
if ($response->getStatusCode() >= 400) {
return false;
}
return true;
}
}