Add max_age argument to send_file()
This commit is contained in:
@@ -662,6 +662,15 @@ object for a file::
|
||||
def index(request):
|
||||
return send_file('/static/index.html')
|
||||
|
||||
A suggested caching duration can be returned to the client in the `max_age`
|
||||
argument::
|
||||
|
||||
from microdot import send_file
|
||||
|
||||
@app.get('/')
|
||||
def image(request):
|
||||
return send_file('/static/image.jpg', max_age=3600) # in seconds
|
||||
|
||||
.. note::
|
||||
Unlike other web frameworks, Microdot does not automatically configure a
|
||||
route to serve static files. The following is an example route that can be
|
||||
@@ -673,7 +682,7 @@ object for a file::
|
||||
if '..' in path:
|
||||
# directory traversal is not allowed
|
||||
return 'Not found', 404
|
||||
return send_file('static/' + path)
|
||||
return send_file('static/' + path, max_age=86400)
|
||||
|
||||
Streaming Responses
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -525,6 +525,10 @@ class Response():
|
||||
#: ``Content-Type`` header.
|
||||
default_content_type = 'text/plain'
|
||||
|
||||
#: The default cache control max age used by :meth:`send_file`. A value
|
||||
#: of ``None`` means that no ``Cache-Control`` header is added.
|
||||
default_send_file_max_age = None
|
||||
|
||||
#: Special response used to signal that a response does not need to be
|
||||
#: written to the client. Used to exit WebSocket connections cleanly.
|
||||
already_handled = None
|
||||
@@ -651,7 +655,8 @@ class Response():
|
||||
return cls(status_code=status_code, headers={'Location': location})
|
||||
|
||||
@classmethod
|
||||
def send_file(cls, filename, status_code=200, content_type=None):
|
||||
def send_file(cls, filename, status_code=200, content_type=None,
|
||||
max_age=None):
|
||||
"""Send file contents in a response.
|
||||
|
||||
:param filename: The filename of the file.
|
||||
@@ -660,6 +665,10 @@ class Response():
|
||||
:param content_type: The ``Content-Type`` header to use in the
|
||||
response. If omitted, it is generated
|
||||
automatically from the file extension.
|
||||
:param max_age: The ``Cache-Control`` header's ``max-age`` value in
|
||||
seconds. If omitted, the value of the
|
||||
:attr:`Response.default_send_file_max_age` attribute is
|
||||
used.
|
||||
|
||||
Security note: The filename is assumed to be trusted. Never pass
|
||||
filenames provided by the user without validating and sanitizing them
|
||||
@@ -671,9 +680,15 @@ class Response():
|
||||
content_type = Response.types_map[ext]
|
||||
else:
|
||||
content_type = 'application/octet-stream'
|
||||
headers = {'Content-Type': content_type}
|
||||
|
||||
if max_age is None:
|
||||
max_age = cls.default_send_file_max_age
|
||||
if max_age is not None:
|
||||
headers['Cache-Control'] = 'max-age={}'.format(max_age)
|
||||
|
||||
f = open(filename, 'rb')
|
||||
return cls(body=f, status_code=status_code,
|
||||
headers={'Content-Type': content_type})
|
||||
return cls(body=f, status_code=status_code, headers=headers)
|
||||
|
||||
|
||||
class URLPattern():
|
||||
|
||||
@@ -235,6 +235,21 @@ class TestResponse(unittest.TestCase):
|
||||
b'HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\nfoo\n')
|
||||
Response.send_file_buffer_size = original_buffer_size
|
||||
|
||||
def test_send_file_max_age(self):
|
||||
res = Response.send_file('tests/files/test.txt', max_age=123)
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertEqual(res.headers['Cache-Control'], 'max-age=123')
|
||||
|
||||
Response.default_send_file_max_age = 456
|
||||
res = Response.send_file('tests/files/test.txt')
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertEqual(res.headers['Cache-Control'], 'max-age=456')
|
||||
res = Response.send_file('tests/files/test.txt', max_age=123)
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertEqual(res.headers['Cache-Control'], 'max-age=123')
|
||||
|
||||
Response.default_send_file_max_age = None
|
||||
|
||||
def test_default_content_type(self):
|
||||
original_content_type = Response.default_content_type
|
||||
res = Response('foo')
|
||||
|
||||
Reference in New Issue
Block a user