feat: Reimplement order and invoice management with new service and repository layers, introduce compression middleware, and update database schema.
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class AdvancedCompressionMiddleware
|
||||
{
|
||||
/**
|
||||
* Compression settings
|
||||
*/
|
||||
private const MIN_LENGTH = 1024; // Minimum content length to compress (1KB)
|
||||
private const COMPRESSION_LEVEL = 6; // Compression level (1-9)
|
||||
private const MAX_COMPRESSION_RATIO = 0.9; // Don't compress if compression ratio > 90%
|
||||
|
||||
/**
|
||||
* Content types that should be compressed
|
||||
*/
|
||||
private const COMPRESSIBLE_TYPES = [
|
||||
'application/json',
|
||||
'text/plain',
|
||||
'text/html',
|
||||
'text/xml',
|
||||
'application/xml',
|
||||
'text/css',
|
||||
'application/javascript',
|
||||
'text/javascript'
|
||||
];
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*/
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
$response = $next($request);
|
||||
|
||||
if (!$this->shouldCompress($request, $response)) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
return $this->compressResponse($request, $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compress the response content
|
||||
*/
|
||||
private function compressResponse(Request $request, Response $response): Response
|
||||
{
|
||||
$content = $response->getContent();
|
||||
$originalLength = strlen($content);
|
||||
|
||||
if ($originalLength < self::MIN_LENGTH) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$acceptEncoding = $request->header('Accept-Encoding', '');
|
||||
$compressed = null;
|
||||
$encoding = null;
|
||||
|
||||
// Try Brotli compression first (best compression ratio)
|
||||
if (str_contains($acceptEncoding, 'br') && function_exists('brotli_compress')) {
|
||||
$compressed = brotli_compress($content, self::COMPRESSION_LEVEL);
|
||||
$encoding = 'br';
|
||||
}
|
||||
// Try Gzip compression
|
||||
elseif (str_contains($acceptEncoding, 'gzip') && function_exists('gzencode')) {
|
||||
$compressed = gzencode($content, self::COMPRESSION_LEVEL);
|
||||
$encoding = 'gzip';
|
||||
}
|
||||
// Fallback to Deflate
|
||||
elseif (str_contains($acceptEncoding, 'deflate') && function_exists('gzdeflate')) {
|
||||
$compressed = gzdeflate($content, self::COMPRESSION_LEVEL);
|
||||
$encoding = 'deflate';
|
||||
}
|
||||
|
||||
// Check compression efficiency
|
||||
if ($compressed !== false && $encoding) {
|
||||
$compressionRatio = strlen($compressed) / $originalLength;
|
||||
|
||||
// Only use compressed content if it's significantly smaller
|
||||
if ($compressionRatio < self::MAX_COMPRESSION_RATIO) {
|
||||
$response->setContent($compressed);
|
||||
$response->headers->set('Content-Encoding', $encoding);
|
||||
$response->headers->set('Content-Length', strlen($compressed));
|
||||
$response->headers->set('Vary', 'Accept-Encoding');
|
||||
|
||||
// Add compression info to headers for debugging
|
||||
if (config('app.debug')) {
|
||||
$response->headers->set('X-Compression-Ratio', round($compressionRatio * 100, 2) . '%');
|
||||
$response->headers->set('X-Original-Size', $originalLength);
|
||||
$response->headers->set('X-Compressed-Size', strlen($compressed));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the response should be compressed
|
||||
*/
|
||||
private function shouldCompress(Request $request, Response $response): bool
|
||||
{
|
||||
// Don't compress if already compressed
|
||||
if ($response->headers->has('Content-Encoding')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't compress file downloads
|
||||
if ($response->headers->has('Content-Disposition')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only compress successful responses
|
||||
if ($response->getStatusCode() >= 400) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if content type is compressible
|
||||
$contentType = $response->headers->get('Content-Type', '');
|
||||
foreach (self::COMPRESSIBLE_TYPES as $type) {
|
||||
if (str_contains($contentType, $type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user