diff --git a/docs/config.rst b/docs/config.rst index fb39b4c4..855136ff 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -130,7 +130,8 @@ The following configuration values are used internally by Flask: ``SEND_FILE_MAX_AGE_DEFAULT`` Default cache control max age to use with :meth:`~flask.Flask.send_static_file` (the default static file handler) and - :func:`~flask.send_file`, in + :func:`~flask.send_file`, as + :class:`datetime.timedelta` or as seconds. seconds. Override this value on a per-file basis using the :meth:`~flask.Flask.get_send_file_max_age` diff --git a/flask/app.py b/flask/app.py index 2d24d8b2..3d741ae9 100644 --- a/flask/app.py +++ b/flask/app.py @@ -246,6 +246,16 @@ class Flask(_PackageBoundObject): permanent_session_lifetime = ConfigAttribute('PERMANENT_SESSION_LIFETIME', get_converter=_make_timedelta) + #: A :class:`~datetime.timedelta` which is used as default cache_timeout + #: for the :func:`send_file` functions. The default is 12 hours. + #: + #: This attribute can also be configured from the config with the + #: ``SEND_FILE_MAX_AGE_DEFAULT`` configuration key. This configuration + #: variable can also be set with an integer value used as seconds. + #: Defaults to ``timedelta(hours=12)`` + send_file_max_age_default = ConfigAttribute('SEND_FILE_MAX_AGE_DEFAULT', + get_converter=_make_timedelta) + #: Enable this if you want to use the X-Sendfile feature. Keep in #: mind that the server has to support this. This only affects files #: sent with the :func:`send_file` method. @@ -297,7 +307,7 @@ class Flask(_PackageBoundObject): 'SESSION_COOKIE_SECURE': False, 'SESSION_REFRESH_EACH_REQUEST': True, 'MAX_CONTENT_LENGTH': None, - 'SEND_FILE_MAX_AGE_DEFAULT': 12 * 60 * 60, # 12 hours + 'SEND_FILE_MAX_AGE_DEFAULT': timedelta(hours=12), 'TRAP_BAD_REQUEST_ERRORS': False, 'TRAP_HTTP_EXCEPTIONS': False, 'EXPLAIN_TEMPLATE_LOADING': False, diff --git a/flask/helpers.py b/flask/helpers.py index 861b21ab..479ca4bb 100644 --- a/flask/helpers.py +++ b/flask/helpers.py @@ -14,6 +14,7 @@ import sys import pkgutil import posixpath import mimetypes +from datetime import timedelta from time import time from zlib import adler32 from threading import RLock @@ -856,7 +857,7 @@ class _PackageBoundObject(object): .. versionadded:: 0.9 """ - return current_app.config['SEND_FILE_MAX_AGE_DEFAULT'] + return total_seconds(current_app.send_file_max_age_default) def send_static_file(self, filename): """Function used internally to send static files from the static @@ -898,3 +899,14 @@ class _PackageBoundObject(object): if mode not in ('r', 'rb'): raise ValueError('Resources can only be opened for reading') return open(os.path.join(self.root_path, resource), mode) + + +def total_seconds(td): + """Returns the total seconds from a timedelta object. + + :param timedelta td: the timedelta to be converted in seconds + + :returns: number of seconds + :rtype: int + """ + return td.days * 60 * 60 * 24 + td.seconds diff --git a/flask/sessions.py b/flask/sessions.py index 1aa42f17..48fd08fa 100644 --- a/flask/sessions.py +++ b/flask/sessions.py @@ -17,14 +17,11 @@ from werkzeug.http import http_date, parse_date from werkzeug.datastructures import CallbackDict from . import Markup, json from ._compat import iteritems, text_type +from .helpers import total_seconds from itsdangerous import URLSafeTimedSerializer, BadSignature -def total_seconds(td): - return td.days * 60 * 60 * 24 + td.seconds - - class SessionMixin(object): """Expands a basic dictionary with an accessors that are expected by Flask extensions and users for the session. diff --git a/tests/test_config.py b/tests/test_config.py index c16bb2f9..7a17b607 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -10,6 +10,7 @@ import pytest import os +from datetime import timedelta import flask @@ -168,6 +169,14 @@ def test_session_lifetime(): assert app.permanent_session_lifetime.seconds == 42 +def test_send_file_max_age(): + app = flask.Flask(__name__) + app.config['SEND_FILE_MAX_AGE_DEFAULT'] = 3600 + assert app.send_file_max_age_default.seconds == 3600 + app.config['SEND_FILE_MAX_AGE_DEFAULT'] = timedelta(hours=2) + assert app.send_file_max_age_default.seconds == 7200 + + def test_get_namespace(): app = flask.Flask(__name__) app.config['FOO_OPTION_1'] = 'foo option 1'