Обслуживать статические файлы и проксировать, если не найдено.

Вопрос или проблема

Я пытаюсь настроить виртуальный хост для работы с прокси, но только если запрос не предназначен для статического файла – в этом случае я хотел бы, чтобы Apache его обслуживал. Вот что я использую:

<VirtualHost *:80>
    ServerName app.local
    DocumentRoot "/app/static"

    # Обслуживание статических файлов
    <Directory "/app/static">
        Require all granted
        Options Indexes FollowSymLinks
        AllowOverride None
    </Directory>

    RewriteEngine On

    RewriteCond %{REQUEST_FILENAME} -f
    RewriteRule ^ - [L]

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^/(.*) http://localhost:8000/$1 [P,L,QSA]

    ProxyPreserveHost On
    ProxyPass / http://localhost:8000/
    ProxyPassReverse / http://localhost:8000/
</VirtualHost>

Тем не менее, если я пытаюсь получить app.local/style.css, этот запрос все равно перенаправляется (я вижу это в логе прокси-сервера), несмотря на то, что файл /app/static/style.css существует. Как мне сделать так, чтобы эти файлы обслуживались?

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/(.*) http://localhost:8000/$1 [P,L,QSA]

Когда вы используете директивы mod_rewrite в контексте виртуального хоста, они обрабатываются до того, как запрос был сопоставлен с файловой системой. Следовательно, переменная сервера REQUEST_FILENAME еще не была оценена и просто содержит корневой относительный путь URL, а не абсолютный путь к файлу. Поэтому условие в вашем первом правиле всегда будет выполняться неудачно, а отрицательное условие выше будет всегда успешным (если только у вас случайно нет абсолютного пути к файлу, который совпадает с путем URL – маловероятно).

Вместо этого вы можете использовать предвосхищение (например, %{LA-U:REQUEST_FILENAME}) или вручную сконструировать абсолютное имя файла, используя переменные сервера DOCUMENT_ROOT и REQUEST_URI (путь URL). Например:

RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
RewriteRule ^/(.*) http://localhost:8000/$1 [P]

Кстати, вам не нужно ваше первое правило, когда у вас есть второе, поскольку они взаимоисключают друг друга.

Флаги L и QSA также избыточны здесь, поскольку P подразумевает L, а строка запроса автоматически добавляется, когда вы явно не включаете строку запроса в замену.

ProxyPass / http://localhost:8000/

Вам также следует удалить директиву ProxyPass, поскольку это приведет к тому, что каждый URL будет проксироваться. Вы используете mod_rewrite (с флагом P) вместо этого, чтобы проксировать запрос.

Ответ или решение

Конфигурация виртуального хоста Apache для обслуживания статических файлов с последующим проксированием запросов, если файлы не найдены, представляет собой типичный сценарий, который может быть использован для повышения производительности веб-сайта. Ниже рассмотрим, как корректно настроить Apache для выполнения этой задачи.

Теория

Основная идея настройки заключается в том, чтобы отделить обработку статических файлов от динамических запросов. Статические файлы, такие как изображения, стили CSS и скрипты JavaScript, могут быть обслужены непосредственно Apache, что гораздо быстрее, чем проксирование через обратный прокси-сервер. Если запрашиваемый файл не является статическим или вообще отсутствует, запрос должен быть перенаправлен на backend сервер через прокси.

Чтобы реализовать это в Apache, настраиваются модули mod_rewrite и mod_proxy. Использование модуля mod_rewrite позволяет задавать условия и правила для маршрутизации URI, основываясь на наличию запрашиваемого файла в файловой системе. Модуль mod_proxy, в свою очередь, используемый для перенаправления запросов на другой сервер, позволяет реализовать проксирование.

Пример

Рассмотрим предоставленный конфигурационный файл Apache:

<VirtualHost *:80>
    ServerName app.local
    DocumentRoot "/app/static"

    # Serve static files
    <Directory "/app/static">
        Require all granted
        Options Indexes FollowSymLinks
        AllowOverride None
    </Directory>

    RewriteEngine On

    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f
    RewriteRule ^ - [L]

    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
    RewriteRule ^/(.*) http://localhost:8000/$1 [P]

    ProxyPreserveHost On
</VirtualHost>

Применение

  1. Настройка DocumentRoot и Directory: Убедитесь, что DocumentRoot указывает на корневой каталог статических файлов, а директива <Directory> настроена на предоставление доступа к этому каталогу. Эти настройки гарантируют, что Apache будет искать файлы в указанной директории.

  2. Использование mod_rewrite:

    • Включите mod_rewrite с помощью RewriteEngine On.
    • Первое RewriteCond проверяет, существует ли файл на диске, используя комбинацию %{DOCUMENT_ROOT} и %{REQUEST_URI}. Условие -f проверяет наличие файла.
    • Если файл существует, правило RewriteRule ^ - [L] останавливает дальнейшую обработку правил, возвратив управление Apache для обслуживания файла.
    • Второе RewriteCond проверяет отсутствие файла. Если файл не найден, правило RewriteRule ^/(.*) http://localhost:8000/$1 [P] перенаправляет запрос на backend сервер через прокси. Флаг P указывает на выполнение проксирования.
  3. Удаление избыточных директив: Убедитесь, что ProxyPass директивы удалены, так как использование mod_rewrite с флагом P для проксирования является достаточным и более гибким.

  4. Оптимизация и наладка: После настройки необходимо протестировать конфигурацию, чтобы убедиться, что статические файлы обслуживаются корректно. Используйте инструменты журналирования Apache и proxy-сервера для диагностики возможных проблем.

Таким образом, данная конфигурация позволяет эффективно разделять обработку статических и динамических запросов, обеспечивая быструю доставку статического контента и корректное проксирование остальных запросов. Кроме того, это способствует уменьшению нагрузки на сервер приложений, поскольку статические файлы не требуют его участия. В конечном итоге, такая настройка улучшает производительность веб-приложения и его отклик для конечных пользователей.

Оцените материал
Добавить комментарий

Капча загружается...