diff --git a/docs/index.rst b/docs/index.rst index 25092fc..5ed9621 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -214,9 +214,18 @@ uploading assets to S3. specified by `flask.url_for`. `S3_HEADERS` Sets custom headers to be sent with each file to S3. **Default:** `{}` +`S3_FILEPATH_HEADERS` Sets custom headers for files whose filepath matches + certain regular expressions. (Note that this cannot + be used for CORS, that must be set per S3 bucket + using an XML config string.) E.g. to add custom + metadata when serving text files, set this to: + `{r'\.txt$':` + ` {'Texted-Up-By': 'Mister Foo'}` + `}` + **Default:** `{}` `S3_ONLY_MODIFIED` Only upload files that have been modified since last upload to S3. SHA-1 file hashes are used to compute - file changes. You can delete `.file-hashes` from + file changes. You can delete `.file-hashes` from your S3 bucket to force all files to upload again. `S3_CACHE_CONTROL` **Deprecated**. Please use `S3_HEADERS` instead. `S3_USE_CACHE_CONTROL` **Deprecated**. Please use `S3_HEADERS` instead. diff --git a/flask_s3.py b/flask_s3.py index 65f4f72..ca3ce8a 100644 --- a/flask_s3.py +++ b/flask_s3.py @@ -3,6 +3,7 @@ import logging import hashlib import json from collections import defaultdict +import re import boto3 import boto3.exceptions @@ -15,6 +16,13 @@ logger = logging.getLogger('flask_s3') import six +def merge_two_dicts(x, y): + '''Given two dicts, merge them into a new dict as a shallow copy.''' + z = x.copy() + z.update(y) + return z + + def hash_file(filename): """ Generate a hash for the contents of a file @@ -149,12 +157,25 @@ def _write_files(s3, app, static_url_loc, static_folder, files, bucket, if ex_keys and full_key_name in ex_keys or exclude: logger.debug("%s excluded from upload" % key_name) else: + h = {} + # Set more custom headers if the filepath matches certain + # configured regular expressions. + filepath_headers = app.config.get('S3_FILEPATH_HEADERS') + if filepath_headers: + for filepath_regex, headers in filepath_headers.iteritems(): + if re.search(filepath_regex, file_path): + for header, value in headers.iteritems(): + h[header] = value + with open(file_path) as fp: s3.put_object(Bucket=bucket, Key=key_name, Body=fp.read(), ACL="public-read", - Metadata=app.config['S3_HEADERS']) + Metadata=merge_two_dicts(app.config['S3_HEADERS'], h)) + + + return new_hashes @@ -300,6 +321,7 @@ class FlaskS3(object): ('S3_CDN_DOMAIN', ''), ('S3_USE_CACHE_CONTROL', False), ('S3_HEADERS', {}), + ('S3_FILEPATH_HEADERS', {}), ('S3_ONLY_MODIFIED', False), ('S3_URL_STYLE', 'host')]