Dancer2::Plugin::ConditionalCaching - RFC7234 Caching
version 0.001
The first three scenarios implicates that no impact in the response is desired. This is accomplished with the parameter check, which should be set to 0.
0
Cache-Control is a mechanism to control a cache. In most cases that is not desired, i.e. the user have to make a request to get fresh data. The corrosponding header is called Cache-Control and valid for both request and response. These paramerters control the header in the response:
cache
When 0, set no-cache
store
When 0, set no-store
public
When 1, set public
private
When 1, set private
no-cache and no-store are mutually exclusive. public and private and mutually exclusive, too.
no-cache also eliminates no-store, public and private.
To tell the client, not to cache the response, say:
caching(check => 0, cache => 0);
To tell the client, not to store the response, say:
caching(check => 0, store => 0);
To tell the client, sharing the response with everyone is okay, say:
caching(check => 0, public => 1);
To tell the client, to keep the response private, say:
caching(check => 0, private => 1);
The keywords must-revalidate and no-transform are sent with every response.
There are three HTTP headers to indicate any time-based state of the response: Age, Expires and Last-Modified.
Last-Modified is redundant to Age, but Last-Modified represents an absolute timestamp whereas Age represents a relative timestamp. Both are controlled by the same parameter.
changed
Accepts a timestamp and calculates Age (now - changed) and set Last-Modified accordingly. Warns if the timestamp is in future - the resulting negative Age value is forced to 0.
expires
Accepts a timestamp and set Expires accordingly. Values in the past are valid.
To tell the client, the response expires in one hour, say:
caching(check => 0, expires => time + 3600);
To tell the client, the data is created half an hour before, say:
caching(check => 0, changed => time - 1800);
These headers are only sent when the request method is HEAD or GET.
An Etag is a counter, a checksum, an unique id, adressing a specific state of data. It's up to you what you provide.
The Etag is taken from the parameter etag. The additional boolean parameter weak indicates that the Etag is weak. Weak Etags compares to both weak and strong Etag whereas a strong Etag (i.e. non-weak Etag) compares only to strong Etags. If you don't know what that means, don't think about it. The Etag is strong by default and that's okay.
To tell the client, the response has the Etag abcdef, say:
abcdef
caching(check => 0, etag => 'abcdef');
This header is only sent when the request method is HEAD or GET.
This step is basically accomplished by omitting the check parameter in the examples above. It compares the request headers and then decides to answer the request with 304 Not Modified status code.
A compare against the Etag takes precedence over time-based constraints. Etags are comapred with the If-None-Match request header, time-based constraints are compared with the If-Modified-Since request header.
To check against the Etag abcdef, and exit the current route with 304 if the Etag matches, say:
caching(etag => 'abcdef');
To check against time-based constraints, say:
caching(changed => time - 3600);
Its not really different to the example above. In case of a conflict, the status code is 412 Precondition Failed. Etags are compared aginst If-Match and time-based constraints are compared against If-Unmodified-Since.
No Cache-Control, Expires, Age or Last-Modified headers are sent.
It's possible that a client may request a state, which should not expire within a specific amount of time. That is accomplished via the min-fresh field inside the Cache-Control request header. And/or the client may also request a state, which is not older than a specific amount of time. That's accomplished via the max-age field in the Cache-Control request header. Both values are compared with created and expires, and the variable force will be set to accordingly. To access that variable, a builder subroutine can be used, which passes some additionals information:
caching(builder => sub { %opts = @_; # requested max-age $maxage = $opts{MaxAge}; # requested min-fresh $minfresh = $opts{MinFresh}; # automatically calculated $force = $opts{Force}; });
Force is 0 by default. When max-age is less than the current age of the data, or when min-fresh is greather than the current freshness (time in seconds till the state expires), then Force is 1.
1
The result of builder is returned by caching.
$one_two_three = caching(builder => sub { return 123; })
If builder is not a CodeRef, the value of that will be returned instead.
$four_five_six = caching(builder => 456);
If you don't want any headers to be set, no exception to be thrown and no auto-exit of the current route, then set dry to 1 and check to 0.
$status_code = caching(dry => 1, check => 0);
The builder subroutine will be still executed, but 200 will be returned instead.
200
And if you just don't want the auto-exit of the current route, but a HTTP::Exception to be thrown, set throw to 1
eval { caching(throw => 1); }; if (my $e = HTTP::Exception->caught) { $status_code = $e->code; # 304 or 412 }
Please report any bugs or feature requests on the bugtracker website https://github.com/zurborg/libdancer2-plugin-conditionalcaching-perl/issues
When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature.
David Zurborg <zurborg@cpan.org>
This software is Copyright (c) 2015 by David Zurborg.
This is free software, licensed under:
The ISC License
To install Dancer2::Plugin::ConditionalCaching, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Dancer2::Plugin::ConditionalCaching
CPAN shell
perl -MCPAN -e shell install Dancer2::Plugin::ConditionalCaching
For more information on module installation, please visit the detailed CPAN module installation guide.