I get the following error whenever a custom domain for the S3 endpoint is used.
# WORKS
AWS_S3_CUSTOM_DOMAIN = 'example.fra1.digitaloceanspaces.com/{}'.format(AWS_STORAGE_BUCKET_NAME)
# DOES NOT WORK ⁉️
AWS_S3_CUSTOM_DOMAIN = 'cdn.example.com/{}'.format(AWS_STORAGE_BUCKET_NAME)
CommandError: An error occurred during rendering /home/<user>/<app>/templates/public/index.html: 'https://cdn.example.com/storage/static/node_modules/nouislider/distribute/nouislider.min.css' isn't accessible via COMPRESS_URL ('https://example.fra1.digitaloceanspaces.com/storage/static/') and can't be compressed
If I go to either url the file is accessible, hence its likely that the CDN is ok, URLs are correctly defined, CORS are fine too.
Also without django-compressor subdomain delivery had been working fine, leading me to believe the issue is not with django-storages
I've been trying for several hours and ultimately had to do a temporary fix by setting the AWS_S3_CUSTOM_DOMAIN to be the same as the AWS_S3_ENDPOINT_URL. However this is not ideal.
Please see the implementation below.
/requirements.txt
Django==3.1.4
...
boto3~=1.16.46
botocore~=1.19.46
s3transfer~=0.3.3
...
django-storages~=1.11.1
django-compressor~=2.4
/config/settings.py
...
# ==========================================================
# DJANGO-STORAGES
# ==========================================================
if LOCALHOST_MODE:
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static/'), ]
else:
AWS_ACCESS_KEY_ID = os.getenv("AWS_ACCESS_KEY_ID")
AWS_SECRET_ACCESS_KEY = os.getenv("AWS_SECRET_ACCESS_KEY")
AWS_STORAGE_BUCKET_NAME = 'storage'
AWS_S3_ENDPOINT_URL = 'https://example.fra1.digitaloceanspaces.com'
# WORKS ⚠️
AWS_S3_CUSTOM_DOMAIN = 'example.fra1.digitaloceanspaces.com/{}'.format(AWS_STORAGE_BUCKET_NAME)
# DOES NOT WORK ⁉️
AWS_S3_CUSTOM_DOMAIN = 'cdn.example.com/{}'.format(AWS_STORAGE_BUCKET_NAME)
AWS_S3_OBJECT_PARAMETERS = {
'CacheControl': 'max-age=86400',
}
AWS_LOCATION = 'static'
AWS_DEFAULT_ACL = 'public-read'
STATICFILES_DIRS = (os.path.join(BASE_DIR, "static"), )
STATIC_URL = '{}/{}/{}/'.format(AWS_S3_ENDPOINT_URL, AWS_STORAGE_BUCKET_NAME, AWS_LOCATION)
STATICFILES_STORAGE = 'storage_backends.CachedS3Boto3Storage'
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
MEDIA_URL = '{}/{}/{}/'.format(AWS_S3_ENDPOINT_URL, AWS_STORAGE_BUCKET_NAME, 'media')
DEFAULT_FILE_STORAGE = 'storage_backends.MediaStorage'
# ==========================================================
# DJANGO-COMPRESSOR
# ==========================================================
COMPRESS_ENABLED = True
STATIC_DEPS = True
COMPRESS_ROOT = os.path.join(BASE_DIR, "static")
COMPRESS_FILTERS = {
'css': ['compressor.filters.css_default.CssAbsoluteFilter', 'compressor.filters.cssmin.rCSSMinFilter'],
'js': ['compressor.filters.jsmin.JSMinFilter']
}
if LOCALHOST_MODE:
COMPRESS_OFFLINE = False
else:
COMPRESS_OFFLINE = True
COMPRESS_STORAGE = STATICFILES_STORAGE
COMPRESS_URL = STATIC_URL
STATICFILES_FINDERS = [
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
'compressor.finders.CompressorFinder',
]
...
/storage_backends.py
from django.core.files.storage import get_storage_class
from storages.backends.s3boto3 import S3Boto3Storage
from config import settings
class MediaStorage(S3Boto3Storage):
bucket_name = settings.AWS_STORAGE_BUCKET_NAME
location = 'media'
class CachedS3Boto3Storage(S3Boto3Storage):
def __init__(self, *args, **kwargs):
super(CachedS3Boto3Storage, self).__init__(*args, **kwargs)
self.local_storage = get_storage_class(
"compressor.storage.CompressorFileStorage")()
def save(self, name, content):
self.local_storage._save(name, content)
super(CachedS3Boto3Storage, self).save(name, self.local_storage._open(name))
return name