<?xml version="1.0" encoding="UTF-8"?>
<ticket>
  <assigned-user-id type="integer">17123</assigned-user-id>
  <attachments-count type="integer">0</attachments-count>
  <closed type="boolean">true</closed>
  <created-at type="datetime">2009-10-03T13:25:04-07:00</created-at>
  <creator-id type="integer">17123</creator-id>
  <milestone-due-on type="datetime">2010-02-08T00:00:00-08:00</milestone-due-on>
  <milestone-id type="integer">41832</milestone-id>
  <number type="integer">247</number>
  <permalink>helpers-for-setting-cache-control-header</permalink>
  <priority type="integer">9</priority>
  <project-id type="integer">9779</project-id>
  <raw-data type="binary" nil="true" encoding="base64"></raw-data>
  <state>resolved</state>
  <tag nil="true"></tag>
  <title>Helper(s) for setting Cache-Control header</title>
  <updated-at type="datetime">2009-10-04T06:29:04-07:00</updated-at>
  <user-id type="integer">11306</user-id>
  <user-name>Simon Rozet</user-name>
  <creator-name>Ryan Tomayko</creator-name>
  <assigned-user-name>Ryan Tomayko</assigned-user-name>
  <url>http://sinatra.lighthouseapp.com/projects/9779/tickets/247</url>
  <milestone-title>1.0</milestone-title>
  <original-body>It bugs me that we don't have a helper for setting cache control headers. Something like:

@@@ ruby
get '/' do
  cache_control :public, :must_revalidate, :max_age =&gt; 60
end
@@@

Here's some high level specs for `cache_control`:

  - Takes a variable number of String or Symbol args for boolean directives (`public`, `no-cache`, `no-store`, `must-revalidate`, `proxy-revalidate`).
  - Takes an optional single Hash arg for value directives (`:max_age =&gt; 60`)
  - Runs a `s/_/-/g` on all directive keys to get the canonical directive name
  - Accepts `true` and `false` as directive Hash values. Directives set `false` are not included in the header value; directives set `true` are included as boolean directives (e.g., `:public =&gt; true` should yield `Cache-Control: public`).

Some concerns:

  - When a Cache-Control header is already set on the response, should the values given to `cache_control` overwrite the existing value or be merged?

  - Does this just write `Cache-Control` headers or can it be used to see what directives are already set. For instance, should we make it possible to `if cache_control[:public]` or `cache_control[:max_age]`?</original-body>
  <latest-body>It bugs me that we don't have a helper for setting cache control headers. Something like:

@@@ ruby
get '/' do
  cache_control :public, :must_revalidate, :max_age =&gt; 60
end
@@@

Here's some high level specs for `cache_control`:

  - Takes a variable number of String or Symbol args for boolean directives (`public`, `no-cache`, `no-store`, `must-revalidate`, `proxy-revalidate`).
  - Takes an optional single Hash arg for value directives (`:max_age =&gt; 60`)
  - Runs a `s/_/-/g` on all directive keys to get the canonical directive name
  - Accepts `true` and `false` as directive Hash values. Directives set `false` are not included in the header value; directives set `true` are included as boolean directives (e.g., `:public =&gt; true` should yield `Cache-Control: public`).

Some concerns:

  - When a Cache-Control header is already set on the response, should the values given to `cache_control` overwrite the existing value or be merged?

  - Does this just write `Cache-Control` headers or can it be used to see what directives are already set. For instance, should we make it possible to `if cache_control[:public]` or `cache_control[:max_age]`?</latest-body>
  <original-body-html>&lt;div&gt;&lt;p&gt;It bugs me that we don't have a helper for setting cache control
headers. Something like:&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;
get '/' do
  cache_control :public, :must_revalidate, :max_age =&amp;gt; 60
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here's some high level specs for &lt;code&gt;cache_control&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Takes a variable number of String or Symbol args for boolean
directives (&lt;code&gt;public&lt;/code&gt;, &lt;code&gt;no-cache&lt;/code&gt;,
&lt;code&gt;no-store&lt;/code&gt;, &lt;code&gt;must-revalidate&lt;/code&gt;,
&lt;code&gt;proxy-revalidate&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Takes an optional single Hash arg for value directives
(&lt;code&gt;:max_age =&amp;gt; 60&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Runs a &lt;code&gt;s/_/-/g&lt;/code&gt; on all directive keys to get the
canonical directive name&lt;/li&gt;
&lt;li&gt;Accepts &lt;code&gt;true&lt;/code&gt; and &lt;code&gt;false&lt;/code&gt; as directive
Hash values. Directives set &lt;code&gt;false&lt;/code&gt; are not included in
the header value; directives set &lt;code&gt;true&lt;/code&gt; are included as
boolean directives (e.g., &lt;code&gt;:public =&amp;gt; true&lt;/code&gt; should
yield &lt;code&gt;Cache-Control: public&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some concerns:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;When a Cache-Control header is already set on the response,
should the values given to &lt;code&gt;cache_control&lt;/code&gt; overwrite the
existing value or be merged?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Does this just write &lt;code&gt;Cache-Control&lt;/code&gt; headers or can
it be used to see what directives are already set. For instance,
should we make it possible to &lt;code&gt;if
cache_control[:public]&lt;/code&gt; or
&lt;code&gt;cache_control[:max_age]&lt;/code&gt;?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;</original-body-html>
  <versions type="array">
    <version type="Ticket::Version">
      <assigned-user-id type="integer">17123</assigned-user-id>
      <attachments-count type="integer">0</attachments-count>
      <body>It bugs me that we don't have a helper for setting cache control headers. Something like:

@@@ ruby
get '/' do
  cache_control :public, :must_revalidate, :max_age =&gt; 60
end
@@@

Here's some high level specs for `cache_control`:

  - Takes a variable number of String or Symbol args for boolean directives (`public`, `no-cache`, `no-store`, `must-revalidate`, `proxy-revalidate`).
  - Takes an optional single Hash arg for value directives (`:max_age =&gt; 60`)
  - Runs a `s/_/-/g` on all directive keys to get the canonical directive name
  - Accepts `true` and `false` as directive Hash values. Directives set `false` are not included in the header value; directives set `true` are included as boolean directives (e.g., `:public =&gt; true` should yield `Cache-Control: public`).

Some concerns:

  - When a Cache-Control header is already set on the response, should the values given to `cache_control` overwrite the existing value or be merged?

  - Does this just write `Cache-Control` headers or can it be used to see what directives are already set. For instance, should we make it possible to `if cache_control[:public]` or `cache_control[:max_age]`?</body>
      <body-html>&lt;div&gt;&lt;p&gt;It bugs me that we don't have a helper for setting cache control
headers. Something like:&lt;/p&gt;
&lt;pre&gt;
&lt;code class=&quot;ruby&quot;&gt;get '/' do
  cache_control :public, :must_revalidate, :max_age =&amp;gt; 60
end&lt;/code&gt;
&lt;/pre&gt;
&lt;p&gt;Here's some high level specs for &lt;code&gt;cache_control&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Takes a variable number of String or Symbol args for boolean
directives (&lt;code&gt;public&lt;/code&gt;, &lt;code&gt;no-cache&lt;/code&gt;,
&lt;code&gt;no-store&lt;/code&gt;, &lt;code&gt;must-revalidate&lt;/code&gt;,
&lt;code&gt;proxy-revalidate&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Takes an optional single Hash arg for value directives
(&lt;code&gt;:max_age =&amp;gt; 60&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Runs a &lt;code&gt;s/_/-/g&lt;/code&gt; on all directive keys to get the
canonical directive name&lt;/li&gt;
&lt;li&gt;Accepts &lt;code&gt;true&lt;/code&gt; and &lt;code&gt;false&lt;/code&gt; as directive
Hash values. Directives set &lt;code&gt;false&lt;/code&gt; are not included in
the header value; directives set &lt;code&gt;true&lt;/code&gt; are included as
boolean directives (e.g., &lt;code&gt;:public =&amp;gt; true&lt;/code&gt; should
yield &lt;code&gt;Cache-Control: public&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some concerns:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;When a Cache-Control header is already set on the response,
should the values given to &lt;code&gt;cache_control&lt;/code&gt; overwrite the
existing value or be merged?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Does this just write &lt;code&gt;Cache-Control&lt;/code&gt; headers or can
it be used to see what directives are already set. For instance,
should we make it possible to &lt;code&gt;if
cache_control[:public]&lt;/code&gt; or
&lt;code&gt;cache_control[:max_age]&lt;/code&gt;?&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;</body-html>
      <closed type="boolean">false</closed>
      <created-at type="datetime">2009-06-08T00:53:51-07:00</created-at>
      <creator-id type="integer">17123</creator-id>
      <diffable-attributes type="yaml">--- {}

</diffable-attributes>
      <milestone-id type="integer">41832</milestone-id>
      <number type="integer">247</number>
      <permalink>helpers-for-setting-cache-control-header</permalink>
      <priority type="integer">0</priority>
      <project-id type="integer">9779</project-id>
      <state>new</state>
      <tag nil="true"></tag>
      <title>Helper(s) for setting Cache-Control header</title>
      <updated-at type="datetime">2009-06-08T00:53:54-07:00</updated-at>
      <user-id type="integer">17123</user-id>
      <user-name>Ryan Tomayko</user-name>
      <creator-name>Ryan Tomayko</creator-name>
      <assigned-user-name>Ryan Tomayko</assigned-user-name>
      <url>http://sinatra.lighthouseapp.com/projects/9779/tickets/247</url>
      <milestone-title>1.0</milestone-title>
    </version>
    <version type="Ticket::Version">
      <assigned-user-id type="integer">17123</assigned-user-id>
      <attachments-count type="integer">0</attachments-count>
      <body>I played with this for an hour or so tonight and pushed the result to the &quot;rtomayko/cachecontrol&quot; branch:

http://github.com/rtomayko/sinatra/commit/8c767c91d4b8c083ff4b0bc53c70fd09c1eb95a4

I don't totally love it but it might be a good start.</body>
      <body-html>&lt;div&gt;&lt;p&gt;I played with this for an hour or so tonight and pushed the
result to the &quot;rtomayko/cachecontrol&quot; branch:&lt;/p&gt;
&lt;p&gt;&lt;a href=
&quot;http://github.com/rtomayko/sinatra/commit/8c767c91d4b8c083ff4b0bc53c70fd09c1eb95a4&quot;&gt;
http://github.com/rtomayko/sinatra/commit/8c767c91d4b8c083ff4b0bc53...&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I don't totally love it but it might be a good start.&lt;/p&gt;&lt;/div&gt;</body-html>
      <closed type="boolean">false</closed>
      <created-at type="datetime">2009-06-08T02:02:31-07:00</created-at>
      <creator-id type="integer">17123</creator-id>
      <diffable-attributes type="yaml">--- 
:state: new
</diffable-attributes>
      <milestone-id type="integer">41832</milestone-id>
      <number type="integer">247</number>
      <permalink>helpers-for-setting-cache-control-header</permalink>
      <priority type="integer">0</priority>
      <project-id type="integer">9779</project-id>
      <state>open</state>
      <tag nil="true"></tag>
      <title>Helper(s) for setting Cache-Control header</title>
      <updated-at type="datetime">2009-06-08T02:02:36-07:00</updated-at>
      <user-id type="integer">17123</user-id>
      <user-name>Ryan Tomayko</user-name>
      <creator-name>Ryan Tomayko</creator-name>
      <assigned-user-name>Ryan Tomayko</assigned-user-name>
      <url>http://sinatra.lighthouseapp.com/projects/9779/tickets/247</url>
      <milestone-title>1.0</milestone-title>
    </version>
    <version type="Ticket::Version">
      <assigned-user-id type="integer">17123</assigned-user-id>
      <attachments-count type="integer">0</attachments-count>
      <body>Looks great IMO. Any reason you didn't push it yet?</body>
      <body-html>&lt;div&gt;&lt;p&gt;Looks great IMO. Any reason you didn't push it yet?&lt;/p&gt;&lt;/div&gt;</body-html>
      <closed type="boolean">false</closed>
      <created-at type="datetime">2009-06-27T14:55:19-07:00</created-at>
      <creator-id type="integer">17123</creator-id>
      <diffable-attributes type="yaml">--- {}

</diffable-attributes>
      <milestone-id type="integer">41832</milestone-id>
      <number type="integer">247</number>
      <permalink>helpers-for-setting-cache-control-header</permalink>
      <priority type="integer">0</priority>
      <project-id type="integer">9779</project-id>
      <state>open</state>
      <tag nil="true"></tag>
      <title>Helper(s) for setting Cache-Control header</title>
      <updated-at type="datetime">2009-06-27T14:55:24-07:00</updated-at>
      <user-id type="integer">11306</user-id>
      <user-name>Simon Rozet</user-name>
      <creator-name>Ryan Tomayko</creator-name>
      <assigned-user-name>Ryan Tomayko</assigned-user-name>
      <url>http://sinatra.lighthouseapp.com/projects/9779/tickets/247</url>
      <milestone-title>1.0</milestone-title>
    </version>
    <version type="Ticket::Version">
      <assigned-user-id type="integer">17123</assigned-user-id>
      <attachments-count type="integer">0</attachments-count>
      <body>Looks good to me. As for your concerns I'd imagine merging, with these options overriding, would be sensible. And the ability to see what's already set might be helpful.

Any reason not to have rack-cache provide this in a leaner require instead of duplicating it? Just seems like two options with people using rack-cache.</body>
      <body-html>&lt;div&gt;&lt;p&gt;Looks good to me. As for your concerns I'd imagine merging, with
these options overriding, would be sensible. And the ability to see
what's already set might be helpful.&lt;/p&gt;
&lt;p&gt;Any reason not to have rack-cache provide this in a leaner
require instead of duplicating it? Just seems like two options with
people using rack-cache.&lt;/p&gt;&lt;/div&gt;</body-html>
      <closed type="boolean">false</closed>
      <created-at type="datetime">2009-08-13T04:58:09-07:00</created-at>
      <creator-id type="integer">17123</creator-id>
      <diffable-attributes type="yaml">--- {}

</diffable-attributes>
      <milestone-id type="integer">41832</milestone-id>
      <number type="integer">247</number>
      <permalink>helpers-for-setting-cache-control-header</permalink>
      <priority type="integer">0</priority>
      <project-id type="integer">9779</project-id>
      <state>open</state>
      <tag nil="true"></tag>
      <title>Helper(s) for setting Cache-Control header</title>
      <updated-at type="datetime">2009-08-13T04:58:10-07:00</updated-at>
      <user-id type="integer">6664</user-id>
      <user-name>Dylan</user-name>
      <creator-name>Ryan Tomayko</creator-name>
      <assigned-user-name>Ryan Tomayko</assigned-user-name>
      <url>http://sinatra.lighthouseapp.com/projects/9779/tickets/247</url>
      <milestone-title>1.0</milestone-title>
    </version>
    <version type="Ticket::Version">
      <assigned-user-id type="integer">17123</assigned-user-id>
      <attachments-count type="integer">0</attachments-count>
      <body>Ryan, IMO these helpers do exactly what I'd expect from Sinatra; small and simple just like the `etag` and `last_modified` ones. I didn't write actual code to try it but wouldn't merging introduce complexity? How'd your merge `cache_control :public, :must_revalidate, :max_age =&gt; 60` with `cache_control :private, :max_age =&gt; 10` for example? It could lead to confusion. Regarding querying, what's the use case? When used as a middleware? Anyway, I think this could be merged as is for now.</body>
      <body-html>&lt;div&gt;&lt;p&gt;Ryan, IMO these helpers do exactly what I'd expect from Sinatra;
small and simple just like the &lt;code&gt;etag&lt;/code&gt; and
&lt;code&gt;last_modified&lt;/code&gt; ones. I didn't write actual code to try
it but wouldn't merging introduce complexity? How'd your merge
&lt;code&gt;cache_control :public, :must_revalidate, :max_age =&amp;gt;
60&lt;/code&gt; with &lt;code&gt;cache_control :private, :max_age =&amp;gt;
10&lt;/code&gt; for example? It could lead to confusion. Regarding
querying, what's the use case? When used as a middleware? Anyway, I
think this could be merged as is for now.&lt;/p&gt;&lt;/div&gt;</body-html>
      <closed type="boolean">false</closed>
      <created-at type="datetime">2009-10-03T13:25:04-07:00</created-at>
      <creator-id type="integer">17123</creator-id>
      <diffable-attributes type="yaml">--- {}

</diffable-attributes>
      <milestone-id type="integer">41832</milestone-id>
      <number type="integer">247</number>
      <permalink>helpers-for-setting-cache-control-header</permalink>
      <priority type="integer">0</priority>
      <project-id type="integer">9779</project-id>
      <state>open</state>
      <tag nil="true"></tag>
      <title>Helper(s) for setting Cache-Control header</title>
      <updated-at type="datetime">2009-10-03T13:26:22-07:00</updated-at>
      <user-id type="integer">11306</user-id>
      <user-name>Simon Rozet</user-name>
      <creator-name>Ryan Tomayko</creator-name>
      <assigned-user-name>Ryan Tomayko</assigned-user-name>
      <url>http://sinatra.lighthouseapp.com/projects/9779/tickets/247</url>
      <milestone-title>1.0</milestone-title>
    </version>
    <version type="Ticket::Version">
      <assigned-user-id type="integer">17123</assigned-user-id>
      <attachments-count type="integer">0</attachments-count>
      <body>Yeah. I'm +1 to go with what's there.</body>
      <body-html>&lt;div&gt;&lt;p&gt;Yeah. I'm +1 to go with what's there.&lt;/p&gt;&lt;/div&gt;</body-html>
      <closed type="boolean">false</closed>
      <created-at type="datetime">2009-10-04T01:41:16-07:00</created-at>
      <creator-id type="integer">17123</creator-id>
      <diffable-attributes type="yaml">--- {}

</diffable-attributes>
      <milestone-id type="integer">41832</milestone-id>
      <number type="integer">247</number>
      <permalink>helpers-for-setting-cache-control-header</permalink>
      <priority type="integer">0</priority>
      <project-id type="integer">9779</project-id>
      <state>open</state>
      <tag nil="true"></tag>
      <title>Helper(s) for setting Cache-Control header</title>
      <updated-at type="datetime">2009-10-04T01:41:18-07:00</updated-at>
      <user-id type="integer">17123</user-id>
      <user-name>Ryan Tomayko</user-name>
      <creator-name>Ryan Tomayko</creator-name>
      <assigned-user-name>Ryan Tomayko</assigned-user-name>
      <url>http://sinatra.lighthouseapp.com/projects/9779/tickets/247</url>
      <milestone-title>1.0</milestone-title>
    </version>
    <version type="Ticket::Version">
      <assigned-user-id type="integer">17123</assigned-user-id>
      <attachments-count type="integer">0</attachments-count>
      <body>(from [c6ea22bb8ff4c8354328db4fa60023c7d494c9bf]) Add cache_control and expires helper methods [#247]
http://github.com/sinatra/sinatra/commit/c6ea22bb8ff4c8354328db4fa60023c7d494c9bf</body>
      <body-html>&lt;div&gt;&lt;p&gt;(from &lt;a href=
&quot;/projects/9779/changesets/c6ea22bb8ff4c8354328db4fa60023c7d494c9bf&quot;
title=
&quot;Changeset [c6ea22bb8ff4c8354328db4fa60023c7d494c9bf]&quot;&gt;[c6ea22bb8ff4c8354328db4fa60023c7d494c9bf]&lt;/a&gt;)
Add cache_control and expires helper methods [&lt;a href=
&quot;/projects/9779/tickets/247&quot; title=&quot;Ticket #247&quot;&gt;#247&lt;/a&gt;] &lt;a href=
&quot;http://github.com/sinatra/sinatra/commit/c6ea22bb8ff4c8354328db4fa60023c7d494c9bf&quot;&gt;
http://github.com/sinatra/sinatra/commit/c6ea22bb8ff4c8354328db4fa6...&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;</body-html>
      <closed type="boolean">false</closed>
      <created-at type="datetime">2009-10-04T06:28:54-07:00</created-at>
      <creator-id type="integer">17123</creator-id>
      <diffable-attributes type="yaml">--- {}

</diffable-attributes>
      <milestone-id type="integer">41832</milestone-id>
      <number type="integer">247</number>
      <permalink>helpers-for-setting-cache-control-header</permalink>
      <priority type="integer">0</priority>
      <project-id type="integer">9779</project-id>
      <state>open</state>
      <tag nil="true"></tag>
      <title>Helper(s) for setting Cache-Control header</title>
      <updated-at type="datetime">2009-10-04T06:28:54-07:00</updated-at>
      <user-id type="integer">17123</user-id>
      <user-name>Ryan Tomayko</user-name>
      <creator-name>Ryan Tomayko</creator-name>
      <assigned-user-name>Ryan Tomayko</assigned-user-name>
      <url>http://sinatra.lighthouseapp.com/projects/9779/tickets/247</url>
      <milestone-title>1.0</milestone-title>
    </version>
    <version type="Ticket::Version">
      <assigned-user-id type="integer">17123</assigned-user-id>
      <attachments-count type="integer">0</attachments-count>
      <body></body>
      <body-html></body-html>
      <closed type="boolean">true</closed>
      <created-at type="datetime">2009-10-04T06:29:01-07:00</created-at>
      <creator-id type="integer">17123</creator-id>
      <diffable-attributes type="yaml">--- 
:state: open
</diffable-attributes>
      <milestone-id type="integer">41832</milestone-id>
      <number type="integer">247</number>
      <permalink>helpers-for-setting-cache-control-header</permalink>
      <priority type="integer">0</priority>
      <project-id type="integer">9779</project-id>
      <state>resolved</state>
      <tag nil="true"></tag>
      <title>Helper(s) for setting Cache-Control header</title>
      <updated-at type="datetime">2009-10-04T06:29:04-07:00</updated-at>
      <user-id type="integer">11306</user-id>
      <user-name>Simon Rozet</user-name>
      <creator-name>Ryan Tomayko</creator-name>
      <assigned-user-name>Ryan Tomayko</assigned-user-name>
      <url>http://sinatra.lighthouseapp.com/projects/9779/tickets/247</url>
      <milestone-title>1.0</milestone-title>
    </version>
  </versions>
</ticket>
