Как мы можем перенаправить на новое статическое содержимое HTML с помощью Apache и вернуться к более старой версии PHP на основе CMS, если не найдено? (nginx try_files)

#php #apache #.htaccess #nginx #mod-rewrite

#php #apache #.htaccess #nginx #mod-переписать

Вопрос:

Проблема :

Мы находимся в процессе замены старого веб-сайта на основе PHP (на основе Statamic v1) на версию SSG HTML, созданную с помощью Gatsby.

Проблема в том, что необходимо заменить только часть существующих страниц, в то время как пространство элементов, а также страницы /login и /contact должны быть сохранены на данный момент.

Итак, мне интересно, как мне адаптировать текущую .htaccess конфигурацию с новой версией, ища сначала новое статическое содержимое, найденное внутри определенного каталога ( public/ ), или, если нет, вернуться к старому index.php?path= методу.

Примечание :

С nginx это было бы сделано с помощью try_files директивы итак, этот вопрос каким-то образом связан с: https://serverfault.com/questions/290784/what-is-apaches-equivalent-of-nginxs-try-files
но я абсолютно не понимаю balancer://app_cluster материала..

Контекст :

Вот упрощенный вид каталогов, поскольку они должны обслуживаться Apache :

 www/
├── index.php
├── (... more CMS files)
└── public
    ├── index.html
    ├── main.js
    ├── robots.txt
    ├── img
    │   ├── intro.jpg
    │   ├── logo.svg
    │   └── table.png
    ├── about
    │   └── index.html
    └── staff
        └── index.html
  

Все, что вводится в public/ , должно быть сначала загружено
без /public появления в конечном URL :

 URL : /img/intro.jpg => /public/img/intro.jpg (rewritten as /img/intro.jpg)
  

И каждый URL, соответствующий /index.html странице, должен быть переписан без нее :

 URL : '' or '/' => /public/index.html (rewritten as '')
URL : /staff or /staff/ => /public/staff/index.html (rewritten as /staff)
  

Каждый файл, который не найден, перенаправляется на /index.php?path=... , как уже сделано сейчас.

Вопрос

Возможно ли это только с Apache, не прибегая к двум отдельным поддоменам и virtual_hosts.. чтобы разделить 2 источника?
Я думаю, что да, учитывая невероятные возможности Apache, но поскольку я теперь больше знаком с nginx, мне действительно нужна ваша помощь здесь !! 🙂

Текущая конфигурация

(не спрашивайте меня, почему)

 # Turn on the Rewrite Engine
RewriteEngine On

# PERMANENT HTTPS REDIRECTION
RewriteCond %{REQUEST_SCHEME} =http
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

# If you're running in a subfolder (like http://example.com/statamic),
# add that here. E.g. /statamic/
RewriteBase /
# Remove trailing slashes from your URL
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/(?.*)?$ $1$2 [R=301,L]

# Remove the index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]

  

Комментарии:

1. Я действительно приветствую короткие ответы, говорящие: да, это возможно , или нет .. потому что.. Это действительно помогло бы мне решить, должен ли я заменить Apache на nginx или на пользовательский прокси, написанный на node.js (я мог бы сделать это наверняка, но это также может ухудшить производительность при обслуживании статических ресурсов ..) Поэтому любая помощь будет высоко оценена ! 🙂

2. Примечание: Дерево иерархии контента можно было бы поменять местами, и мы могли бы также изучить возможность использования статического сайта в качестве root, а устаревшей PHP CMS — в подпапке, возможно, это могло бы быть более эффективным..

Ответ №1:

Если я правильно понимаю, их ключевое требование — обслуживать статический контент в public/ , если он существует, а если нет, передать запрос в index.php .

Это требование относительно легко выполнить. Порядок правил важен, поскольку они применяются последовательно для каждого входящего запроса. Мы можем сначала выполнить проверку public/ содержимого, поэтому, если оно там существует, мы предпочтительно вернем его и остановим обработку. Если запрос не соответствует этому тесту, обработка будет продолжена до index.php перенаправления.

 RewriteEngine On

# If the requested file or directory exists in public/, internally redirect
# there (internally means no actual new http request, and the URL in the
# browser does not change).  Use OR flag to OR the 2 conditions, instead of
# the usual implicit AND.
RewriteCond %{DOCUMENT_ROOT}/public%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}/public%{REQUEST_URI} -d
RewriteRule ^.*$ public/%{REQUEST_URI} [L]

# If the requested file does not exist, and is not a directory, pass the
# request to index.php, appending any query string.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]
  

Обратите внимание, что вы упомянули:

Каждый файл, который не найден, перенаправляется в /index.php?path = … как уже сделано сейчас.

Просто для ясности, на самом деле это не то, что .htaccess вы включили сейчас. Это правило просто передает запрос в index.php , без path параметра (хотя включает любые существующие параметры, которые уже есть в запросе). Ваш index.php может получить доступ — и, несомненно, уже получает — к реальному запрошенному пути, используя $_SERVER переменные. Но если вы действительно хотите теперь добавить путь к запросу, как вы описываете, вам придется изменить это правило на что-то вроде:

 RewriteRule ^(.*)$ index.php?path=$1 [QSA,L]
  

Еще одно замечание — как в вопросе, так и в .htaccess что, я думаю, запутывает проблему и, возможно, поэтому вы не получили здесь хорошего ответа.

Комментарии:

1. Большое спасибо! Ваш ответ действительно ясен, и я почти уверен, что он работает, даже если я не потрудился протестировать его прямо сейчас. Это появилось немного слишком поздно, но я все равно очень благодарен: кто-нибудь наверняка найдет это полезным 🙂