Skip to content

Commit

Permalink
Merge pull request #64 from virtosubogdan/prefixing_and_versioning
Browse files Browse the repository at this point in the history
Add support for static file versioning and prefixing.
  • Loading branch information
Isaac Dickinson committed Mar 13, 2016
2 parents 120339d + b323e2b commit dfb9d8e
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 3 deletions.
23 changes: 20 additions & 3 deletions flask_s3.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@

__version__ = (0, 2, 10)


def _get_statics_prefix(app):
"""
Get the complete prefix that should be used by static files.
"""
upload_prefix = app.config.get('FLASKS3_PREFIX', '')
return '/%s' % upload_prefix.lstrip('/').rstrip('/')


def split_metadata_params(headers):
"""
Given a dict of headers for s3, seperates those that are boto3
Expand Down Expand Up @@ -122,6 +131,10 @@ def url_for(endpoint, **values):

if app.config['FLASKS3_CDN_DOMAIN']:
bucket_path = '%s' % app.config['FLASKS3_CDN_DOMAIN']

# Both S3 and CDN urls should use the prefix if it exists
bucket_path += _get_statics_prefix(app).rstrip('/')

urls = app.url_map.bind(bucket_path, url_scheme=scheme)
return urls.build(endpoint, values=values, force_external=True)
return flask_url_for(endpoint, **values)
Expand Down Expand Up @@ -271,9 +284,11 @@ def _write_files(s3, app, static_url_loc, static_folder, files, bucket,

def _upload_files(s3, app, files_, bucket, hashes=None):
new_hashes = []
prefix = _get_statics_prefix(app)
for (static_folder, static_url), names in six.iteritems(files_):
new_hashes.extend(_write_files(s3, app, static_url, static_folder, names,
bucket, hashes=hashes))
static_upload_url = '%s/%s' % (prefix.rstrip('/'), static_url.lstrip('/'))
new_hashes.extend(_write_files(s3, app, static_upload_url, static_folder,
names, bucket, hashes=hashes))
return new_hashes


Expand Down Expand Up @@ -473,7 +488,9 @@ def init_app(self, app):
('FLASKS3_URL_STYLE', 'host'),
('FLASKS3_GZIP', False),
('FLASKS3_GZIP_ONLY_EXTS', []),
('FLASKS3_FORCE_MIMETYPE', False)]
('FLASKS3_FORCE_MIMETYPE', False),
('FLASKS3_PREFIX', '')]


for k, v in defaults:
app.config.setdefault(k, v)
Expand Down
39 changes: 39 additions & 0 deletions test_flask_static.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ def setUp(self):
self.app.config['FLASKS3_BUCKET_NAME'] = 'foo'
self.app.config['FLASKS3_USE_CACHE_CONTROL'] = True
self.app.config['FLASKS3_CACHE_CONTROL'] = 'cache instruction'
self.app.config['S3_CACHE_CONTROL'] = '3600'
self.app.config['FLASKS3_HEADERS'] = {
'Expires': 'Thu, 31 Dec 2037 23:59:59 GMT',
'Content-Encoding': 'gzip',
Expand Down Expand Up @@ -394,6 +395,44 @@ def test_static_folder_path(self):
for i, e in zip(inputs, expected):
self.assertEquals(e, flask_s3._static_folder_path(*i))

@patch('flask_s3._write_files')
def test__upload_uses_prefix(self, mock_write_files):
s3_mock = Mock()
local_path = '/local_path/static'
file_paths = ['/local_path/static/file1', '/local_path/static/file2']
files = {(local_path, '/static'): file_paths}

flask_s3._upload_files(s3_mock, self.app, files, 's3_bucket')
expected_call = call(
s3_mock, self.app, '/static', local_path, file_paths, 's3_bucket', hashes=None)
self.assertEquals(mock_write_files.call_args_list, [expected_call])

for supported_prefix in ['foo', '/foo', 'foo/', '/foo/']:
mock_write_files.reset_mock()
self.app.config['FLASKS3_PREFIX'] = supported_prefix
flask_s3._upload_files(s3_mock, self.app, files, 's3_bucket')
expected_call = call(s3_mock, self.app, '/foo/static',
local_path, file_paths, 's3_bucket', hashes=None)
self.assertEquals(mock_write_files.call_args_list, [expected_call])

@patch('flask_s3.current_app')
def test__url_for_uses_prefix(self, mock_current_app):
bucket_path = 'foo.s3.amazonaws.com'
flask_s3.FlaskS3(self.app)
mock_current_app.config = self.app.config
mock_bind = mock_current_app.url_map.bind

flask_s3.url_for('static', **{'filename': 'test_file.txt'})
self.assertEqual(mock_bind.call_args_list, [call(bucket_path, url_scheme='https')])

for supported_prefix in ['bar', '/bar', 'bar/', '/bar/']:
mock_bind.reset_mock()
self.app.config['FLASKS3_PREFIX'] = supported_prefix
flask_s3.url_for('static', **{'filename': 'test_file.txt'})
expected_path = '%s/%s' % (bucket_path, 'bar')
self.assertEqual(mock_bind.call_args_list,
[call(expected_path, url_scheme='https')])


if __name__ == '__main__':
unittest.main()

0 comments on commit dfb9d8e

Please sign in to comment.