Skip to content

Commit

Permalink
?_ttl= parameter and default_cache_ttl config
Browse files Browse the repository at this point in the history
Refs #285, Closes #289
  • Loading branch information
simonw committed May 26, 2018
1 parent a6afc21 commit b463f60
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 1 deletion.
3 changes: 3 additions & 0 deletions datasette/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@
ConfigOption("allow_sql", True, """
Allow arbitrary SQL queries via ?sql= parameter
""".strip()),
ConfigOption("default_cache_ttl", 365 * 24 * 60 * 60, """
Default HTTP cache TTL (used in Cache-Control: max-age= header)
""".strip()),
)
DEFAULT_CONFIG = {
option.name: option.default
Expand Down
12 changes: 11 additions & 1 deletion datasette/views/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,17 @@ async def view_get(self, request, name, hash, **kwargs):
r.status = status_code
# Set far-future cache expiry
if self.ds.cache_headers:
r.headers["Cache-Control"] = "max-age={}".format(365 * 24 * 60 * 60)
ttl = request.args.get("_ttl", None)
if ttl is None or not ttl.isdigit():
ttl = self.ds.config["default_cache_ttl"]
else:
ttl = int(ttl)
if ttl == 0:
ttl_header = 'no-cache'
else:
ttl_header = 'max-age={}'.format(ttl)
r.headers["Cache-Control"] = ttl_header
r.headers["Referrer-Policy"] = "no-referrer"
return r

async def custom_sql(
Expand Down
9 changes: 9 additions & 0 deletions docs/config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,12 @@ allow_sql
Enable/disable the ability for users to run custom SQL directly against a database. To disable this feature, run::

datasette mydatabase.db --config allow_sql:off

default_cache_ttl
-----------------

Default HTTP caching max-age header in seconds, used for ``Cache-Control: max-age=X``. Can be over-ridden on a per-request basis using the ``?_ttl=`` querystring parameter. Set this to ``0`` to disable HTTP caching entirely. Defaults to 365 days (31536000 seconds).

::

datasette mydatabase.db --config default_cache_ttl:10
4 changes: 4 additions & 0 deletions docs/json_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,10 @@ The Datasette table view takes a number of special querystring arguments:
long, for example if you want to implement autocomplete search but only if
it can be executed in less than 10ms.

``?_ttl=SECONDS``
For how many seconds should this response be cached by HTTP proxies? Use
``?_ttl=0`` to disable HTTP caching entirely for this request.

``?_next=TOKEN``
Pagination by continuation token - pass the token that was returned in the
``"next"`` property by the previous page.
12 changes: 12 additions & 0 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,7 @@ def test_config_json(app_client):
"allow_facet": True,
"suggest_facets": True,
"allow_sql": True,
"default_cache_ttl": 365 * 24 * 60 * 60,
} == response.json


Expand Down Expand Up @@ -1127,3 +1128,14 @@ def test_suggest_facets_off():
"/test_tables/facetable.json",
gather_request=False
).json["suggested_facets"]


@pytest.mark.parametrize('path,expected_cache_control', [
("/test_tables/facetable.json", "max-age=31536000"),
("/test_tables/facetable.json?_ttl=invalid", "max-age=31536000"),
("/test_tables/facetable.json?_ttl=10", "max-age=10"),
("/test_tables/facetable.json?_ttl=0", "no-cache"),
])
def test_ttl_parameter(app_client, path, expected_cache_control):
response = app_client.get(path, gather_request=False)
assert expected_cache_control == response.headers['Cache-Control']

0 comments on commit b463f60

Please sign in to comment.