Доступ запрещен к файлу css, который является общедоступным на S3 AWS bucket
Итак, у меня есть приложение Django, запущенное в контейнере docker на AWS EC2. Статический контент размещен на S3 bucket (css, javascript и т.д.). Все это прекрасно работает.
Я реализовал вывод PDF для некоторых файлов с помощью weasy print. Локально он выводит ожидаемый PDF нормально. Однако на сервере я получаю ошибку 500. При ближайшем рассмотрении в логах django, которые я добавил к моему декоратору (который отвечает за генерацию PDF), появилась следующая ошибка. Декоратор декорирует некоторый дескриптор, который вызывается, и созданный PDF появляется в папке загрузки.
Декорированный обработчик:
@generate_pdf_httpresponse
def handler_warehouse_packingslip(request, **kwargs):
id = kwargs.get("pk")
context = { .... details to provide to print.... }
filename = "foo.pdf"
infos = {"context":context, "template_path":'projectlibs/pdf_outputs/pdf_base.html', "extra_css_files":[], "filename":filename,"request":request}
return infos
Декоратор:
def generate_pdf_httpresponse(func):
@functools.wraps(func)
def wrapper_generate_pdf_httpresponse(*args, **kwargs):
try:
logger.info(f"Wrapper for pdf response")
value = func(*args, **kwargs)
html_string = render_to_string(value.get("template_path"), context=value["context"])
html = HTML(string=html_string, base_url=value["request"].build_absolute_uri())
css_files = []
pdf = html.write_pdf(stylesheets=css_files)
logger.info(f"Creating tmp file for pdf response")
with tempfile.NamedTemporaryFile() as file:
file.write(pdf)
file.seek(0)
stream = file.read()
httpresponse = HttpResponse(content_type='application/pdf;', content=stream)
httpresponse['Content-Disposition'] = f'attachment; filename={value["filename"]}'
httpresponse['Content-Transfer-Encoding'] = 'binary'
return httpresponse
except Exception as ex:
logger.error(f"PDF wrapper failed: {ex}")
return wrapper_generate_pdf_httpresponse
Что приводит к такой ошибке (на aws):
27/12/21 14:03:43 INFO DEFAULT: Wrapper for pdf response
27/12/21 14:03:43 INFO DEFAULT: Request to print packing skips warehouse....
27/12/21 14:03:43 ERROR DEFAULT: PDF wrapper failed: Attempted access to '/css/pdf2.css' denied.
Но этот файл общедоступен - я могу получить к нему прямой доступ из веба (https://<my_s3_bucketname>.s3.amazonaws.com/static/css/pdf2.css). Основная таблица стилей, которую я использую, также доступна там, на нее ссылаются те же теги & все работает нормально.
<<link rel="stylesheet" type="text/css" href="{% static 'css/mystyle.css' %}">
Например, это работает нормально:
Но не это:
<link href="{% static '/css/pdf2.css' %}" rel="stylesheet" type="text/css" >
Где/как я должен устранить неполадки?
Проверено:
- pdf2.css существует в статическом ведре s3 (и это отказ в доступе, а не not found)
Итак, мне не удалось найти ответа на первоначальный вопрос (кто-то написал комментарий о том, что файлы css не обслуживаются из ведра S3 в случае с pdf, но я не совсем понял, что он имел в виду, и он удалил комментарий).
Однако одно изменение, которое действительно работает, заключается в замене ссылки css в шаблоне и переносе ее в weasy-print. Из приведенного выше кода:
from django.conf import settings
css_files = [ f"{settings.STATICFILES_DIRS[0]}/css/pdf2.css"]
при условии правильной установки STATICFILES_DIRS в settings.py
Затем удалите <link href="{% static '/css/pdf2.css' %}" rel="stylesheet" type="text/css" >
.
Затем, поскольку weasy print получает фактический файл локально (например, из экземпляра EC2, в его статической папке), то это работает. Я полагаю, поскольку это также фиксируется в git из того же конвейера (например, collecstatic и т.д.), это достойное решение с точки зрения devops, не требующее специальных шагов/конфигов.