60

I want to set headers as array('Cache-Control'=>'no-cache, no-store, max-age=0, must-revalidate','Pragma'=>'no-cache','Expires'=>'Fri, 01 Jan 1990 00:00:00 GMT'); for all my views, currently I'm doing this in all controllers while returning views, like

$headers=array('Cache-Control'=>'no-cache, no-store, max-age=0, must-revalidate','Pragma'=>'no-cache','Expires'=>'Fri, 01 Jan 1990 00:00:00 GMT');

Redirect::to('/',301,$headers);`

So instead of writing this for each and every route can it be done in global scope, so that headers are set for every view.

I tried setting headers by creating after filter, but didn't get it to work.

Can anyone tell me where can I set the headers for all my views?

UPDATE One of my view file meta content

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>

Now when i use Redirect::to('/',301,$headers) The header in firebug is

Cache-Control   max-age=0, must-revalidate, no-cache, no-store, private
Connection  Keep-Alive
Content-Type    text/html; charset=UTF-8
Date    Tue, 09 Jul 2013 14:52:08 GMT
Expires Fri, 01 Jan 1990 00:00:00 GMT

And when I use Redirect::to('/');

The header in firebug is

Cache-Control   no-cache
Connection  Keep-Alive
Content-Type    text/html; charset=UTF-8
Date    Tue, 09 Jul 2013 14:52:08 GMT
Antonio Carlos Ribeiro
  • 86,191
  • 22
  • 213
  • 204
Trying Tobemyself
  • 3,668
  • 3
  • 28
  • 43

7 Answers7

44

In Laravel 5, using Middleware, creating a new file, modifying an existing file:

New file: app/Http/Middleware/AddHeaders.php

<?php namespace App\Http\Middleware;

use Closure;
use Illuminate\Contracts\Routing\Middleware;

// If Laravel >= 5.2 then delete 'use' and 'implements' of deprecated Middleware interface.
class AddHeaders implements Middleware
{
    public function handle($request, Closure $next)
    {
        $response = $next($request);
        $response->header('header name', 'header value');
        $response->header('another header', 'another value');

        return $response;
    }
}

Modify existing file app/Kernel.php

protected $middleware = [
.
.
.

        'App\Http\Middleware\AddHeaders',
    ];

And you're set.

Amarnasan
  • 14,939
  • 5
  • 33
  • 37
39

There are a couple of different ways you could do this - all have advantages/disadvantages.

Option 1 (simple): Since the array is just static data - just manually put the headers in your view layouts directly - i.e. dont pass it from anywhere - code it straight in your view.

<?php
  //set headers to NOT cache a page
  header("Cache-Control: no-cache, must-revalidate"); //HTTP 1.1
  header("Pragma: no-cache"); //HTTP 1.0
  header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
?>

Option 2: Use view composers. You can use an App before filter to bind the header to all views in your app.

App::before(function($request)  
{
     $headers=array('Cache-Control'=>'no-cache, no-store, max-age=0, must-revalidate','Pragma'=>'no-cache','Expires'=>'Fri, 01 Jan 1990 00:00:00 GMT');

     View::share('headers', $headers);
}); 

Then just echo out the $headers in your view(s).

Note: you must let the view set your headers - that is why we are 'passing' the header into view for Laravel to handle. If you try and output the header itself from within a filter or something, you'll cause issues.

Edit Option 3: I just found out about this - you could try this

App::before(function($request)  
{
     Response::header('Cache-Control', 'nocache, no-store, max-age=0, must-revalidate');
     Response::header('Pragma', 'no-cache');
     Response::header('Expires', 'Fri, 01 Jan 1990 00:00:00 GMT');
}); 
Laurence
  • 58,936
  • 21
  • 171
  • 212
  • sorry but i didn't get you. What is the use of passing headers to view?? – Trying Tobemyself Jul 09 '13 at 14:10
  • thats my point - just code the header directly in the view (Option 1). But if for some reason you dont want to do that, you could 'pass' the headers into the view using a view composer. – Laurence Jul 09 '13 at 14:13
  • Are you talking about meta tags? if yes then i already did that but it is not solving my problem. And about view composer, I don't think that we can set the headers in view composer because headers can only be set using response object and in composer we don't get response object – Trying Tobemyself Jul 09 '13 at 14:14
  • "" is a header. When you "set headers" - all that is occuring is that text appears at the top of your html file. So you can either do that with a view composer, or just type it yourself at the top of the file. That is all Laravel does when you set headers - it puts that text at the top of your html file – Laurence Jul 09 '13 at 14:18
  • 10
    Response::header() is not available in L4 – Trying Tobemyself Jul 09 '13 at 15:09
  • i've editted option 1 for you - just put that at the top of your layouts – Laurence Jul 09 '13 at 15:50
  • Thank you that did the trick, but instead of putting that in view layout,I ended up putting in after filter – Trying Tobemyself Jul 09 '13 at 16:30
30

In Laravel 4, this works for me:

In filters.php:

App::after(function($request, $response)
{
   $response->headers->set('key','value');
});

Like:

App::after(function($request, $response)
{
   $response->headers->set('P3P','CP="NOI ADM DEV PSAi COM NAV OUR OTR STP IND DEM"');
});
Ben Bos
  • 2,351
  • 1
  • 19
  • 13
12

In Laravel 5 you can change /public/index.php line 55 to set your header for entire app:

$response->send();

with:

$response->header('Content-Type','text/html; charset=ISO-8859-1')->send();

for example.

wruckie
  • 1,717
  • 1
  • 23
  • 34
Marius Catalin
  • 137
  • 1
  • 2
  • Where were you one hour ago when I was trying to change the encoding to windows-1252 ? :'( – Amarnasan Jul 23 '15 at 12:12
  • I found a new, better method: In /vendor/laravel/framework/src/Illuminate/Http/Response.php add `protected $charset='ISO-8859-1';` after ` public $original;` – Marius Catalin Aug 04 '15 at 08:05
  • 2
    Is it ever a good idea to change core framework files when there is a great system like middlewares available to do this? – Ezra Dec 10 '15 at 09:22
  • Never change core files, they should be overwritten on the next Laravel update. – PaulH Jan 14 '22 at 15:25
10

For future readers using Laravel 5.x, this can be handled out of the box without needing to create any custom middleware.

Laravel has the response() helper method, which you can chain headers to very easily.

use Response;
// Or possibly: use Illuminate\Http\Response; depending on your aliases used.

// Add a series of headers
return response($content)
    ->header('Content-Type', 'text/xml')
    ->header('X-Header-One', 'Header Value');

// Or use withHeaders to pass array of headers to be added
return response($content)
    ->withHeaders([
        'Content-Type' => 'text/xml',
        'X-Header-One' => 'Header Value'
    ]);

Read more about it in the documentation, because it can handle attaching a number of things; cookies, views, and more.

camelCase
  • 5,460
  • 3
  • 34
  • 37
7

For Laravel >= 5.2 yet, following @Amarnasan answer , although I used mine for API calls

In Laravel 5, using Middleware, creating a new file, modifying an existing file:

New file: app/Http/Middleware/AddHeaders.php

<?php 
namespace App\Http\Middleware;
use Closure;
use Illuminate\Routing\Redirector;
use Illuminate\Http\Request;
use Illuminate\Foundation\Applicaion;


class AddHeaders 
{
    public function handle($request, Closure $next)
    {
        $response = $next($request);
        $response->header('Cache-Control', 'max-age=36000, public');
        //$response->header('another header', 'another value');

        return $response;
    }
}

Modify existing file app/Kernel.php so that you can use with each specific route

protected $routeMiddleware = [
.
.
.

        'myHeader' => \App\Http\Middleware\AddHeaders::class,
    ];

And you're set.

Then you can use it like so for individual routes or groups

$api->get('cars/all', 'MyController@index')->middleware(['myHeader']);;
BlackPearl
  • 2,532
  • 3
  • 33
  • 49
5

Working on Laravel 4.2. I'm using filter for this, so in filters.php i have:

Route::filter('no-cache',function($route, $request, $response){

    $response->header("Cache-Control","no-cache,no-store, must-revalidate");
    $response->header("Pragma", "no-cache"); //HTTP 1.0
    $response->header("Expires"," Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past

});

Than I attach this filter to routes or controllers. Controller attached looks like this for me:

public function __construct() {

        $this->beforeFilter('onestep',array('except' => 'getLogin'));
        $this->beforeFilter('csrf',array('on' => 'post'));
        $this->afterFilter("no-cache", ["only"=>"getIndex"]);
    }

This filter is attached as afterFilter.

MikeWu
  • 3,042
  • 2
  • 19
  • 27
  • Can you please explain what does 'onestep' filter do? If possible, please share the 'onestep' filter code snippet. – Tahsin Abrar Nov 16 '14 at 05:03
  • Using a route filter to do this gives you the ability to only kill caching on certain routes. Use the `after` hook to set http headers. e.g. `Route::get('/hello', array('after' => 'no-cache', 'uses' => 'HelloController@index'));` – sgb Dec 03 '14 at 15:28