yukulelix's avatar

Add Content-Length Header on views

Hi there, I am trying to create loading bars for my ajax powered website.

I would need Laravel to put a content-length header on my php pages. Any ideas on how to do that ?

Cheers !

Félix

0 likes
6 replies
xingfucoder's avatar

Hi @yukulelix if you have access to the response object you may use as follow:

$response->headers->set('key','value');

I think using a Global Middleware you could specify that.

Hope it helps you.

usman's avatar
usman
Best Answer
Level 27

@yukulelix :

//file: app/Http/Middleware/AddContentLength.php
<?php namespace App\Http\Middleware;

use Closure;

class AddContentLength {

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $response = $next($request);
        $response->header('Content-Length',strlen($response->getOriginalContent()));
        return $response;
    }
}

Add the middleware inside app/Http/Kernel.php:

    protected $middleware = [
        '...............',
        'App\Http\Middleware\VerifyCsrfToken',
        'App\Http\Middleware\AddContentLength'
    ];

Usman.

4 likes
orrd's avatar

Thanks to @usman for the code sample. There is one small correction that should be made, and a big caveat to be aware of. First, I would recommend changing getOriginalContent() to content() because getOriginalContent() won't be the actual content that is sent to the browser in some cases. But also be aware that the Content-Length won't be accurate if gzip or deflate compression is used (including if you're using mod_deflate or if 'zlib.output_compression' is turned on) ... and you probably should be using one of those by the way if you aren't already since they'll help speed up your website for users.

Now, if you do want to use compressed output and you also really want to set the content length, you have to compress the output yourself. You can use this to compress the content instead of usin mod_deflate or if zlib.output_compression (see @usman's answer for info about how to insert this middleware code into your project):

class AddContentLength {

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $response = $next($request);

        // to be sure nothing was already output (by an echo statement or something)
        if (headers_sent() || ob_get_contents() != '') return $response;

        $content = $response->content();
        $contentLength = strlen($content);
        $useCompressedOutput = ($contentLength && isset($_SERVER['HTTP_ACCEPT_ENCODING']) &&
           strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false);
        
        if ($useCompressedOutput) {
            // In order to accurately set Content-Length, we have to compress the data ourselves 
            // rather than letting PHP do it automatically.
            $compressedContent = gzencode($content, 9, FORCE_GZIP);
            $compressedContentLength = strlen($compressedContent);
            if ($compressedContentLength/$contentLength < 0.9) {
                if (ini_get('zlib.output_compression')) ini_set('zlib.output_compression', false);
                $response->header('Content-Encoding', 'gzip');
                $response->setContent($compressedContent);
                $contentLength = $compressedContentLength;
            }
        }
        
        // compressed or not, sets the Content-Length           
        $response->header('Content-Length', $contentLength);
    
        return $response;
    }
}
1 like
inad9300's avatar

Regarding the @usman answer, consider using mb_strlen() (together with mb_internal_encoding()) instead of strlen(), as it takes care of the character encoding to properly calculate the length.

1 like

Please or to participate in this conversation.