6

It seems that by default Catalyst does not output Cache-Control:, etc. headers. I know I can output them in a given controller method like this:

$c->response->headers->last_modified(time);
$c->response->headers->expires(time + $self->{cache_time});
$c->response->headers->header(cache_control => "public, max-age=$self->{cache_time}");

It'd get pretty painful doing that in each method, though! What I'd prefer is:

  • A default set of headers (expires now, last modified now, cache-control: no-cache, pragma: no-cache)
  • A way to, per-method, override the default.

Is there a good way to accomplish this?

brian d foy
  • 129,424
  • 31
  • 207
  • 592
derobert
  • 49,731
  • 15
  • 94
  • 124

2 Answers2

6

derobert:

Excellent question. I covered exactly this in an article for the Catalyst advent calendar.

Basically you create a stash variable that defines your cache time for the given action, and then you process it in your Root end routine. See the article for all the details.

JayK

jayk
  • 189
  • 1
  • 3
    You may want to include a short snippet in this answer. – Brad Gilbert Jul 24 '09 at 17:58
  • That wiki isn't loading for me at the moment (blank page or connection reset), but I can work with that idea. Thanks. And I can just default it to no-cache if one isn't set. Amazing this isn't built in to Catalyst; seems like every Catalyst app must have to do this! – derobert Jul 27 '09 at 14:18
  • Ok, the wiki is back up. That's a really nice approach. That really ought to be part of Catalyst, or at least a plugin.... – derobert Jul 27 '09 at 14:53
  • People use Catalyst for a lot of different things and generally speaking we try to avoid adding things to Catalyst core when they aren't essential. The method is so simple that it's hardly worth creating a whole add-on for it. We usually just point folks in the direction of that wiki entry, as the whole addition is 12 lines not including comments. :-D – jayk Jul 28 '09 at 19:42
4

Update: Based on your response to my earlier suggestion, I decided to bite the bullet and look at the Catalyst docs. It seems to me, the place to do this is in:

  sub end : Private {
    my ( $self, $c ) = @_;

    # handle errors etc.

    if ( $c->res->body ) {
        if ( "some condition" ) {
            set_default_response_headers( $c->response->headers );
            return;
        }
        else {
            do_something_else();
            return;
        }
    }
    $c->forward( 'MyApp::View::TT' ); # render template
}

Earlier response: I do not use Catalyst, but couldn't you just write a sub for your application?

sub set_default_response_headers {
    my ($h) = @_;
    $h->last_modified(time);
    $h->expires(time + $self->{cache_time});
    $h->header(cache_control => "public, max-age=$self->{cache_time}");
    return $h;    
}

Call with set_default_response_headers( $c->response->headers ).

Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339
  • Yes, I could write a sub, but then I still have to remember to call it in every method... and if it gets forgotten in any controller method, it leads to a probable bug. Seems like a rather fragile approach – derobert Jul 24 '09 at 13:52