Доступ запрещен к файлу 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, не требующее специальных шагов/конфигов.

Вернуться на верх