Несколько приложений, несколько версий приложения в одном домене. Как настроить сервер Apache, маршруты и относительные пути, чтобы он работал? - PullRequest
0 голосов
/ 09 ноября 2019

Сервер моей команды настроен следующим образом: у нас есть одно доменное имя, которое, похоже, уже является поддоменом домена компании. Мы хотим разместить несколько приложений в этом одном домене. Мы даже хотели бы иметь рабочую версию и промежуточную версию для каждого приложения на сервере.

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

Вот структура, эквивалентная тому, как организованы каталоги.

/usr/local/var/www  <- Document Root
/usr/local/var/app1 <- application 1
------------------/public/index.php
------------------/public/css
/usr/local/var/app2 <- application 2
/usr/local/var/app1.stg <- application 1 staging version, code is exactly the same as application1
/usr/local/var/app2.stg <- application 2 staging version, code is exactly the same as application2

Вот соответствующие настройки в httpd.conf

DocumentRoot /usr/local/var/www
<Directory "/usr/local/var/www">
    AllowOverride None
    Require all granted
</Directory>
Alias "/app1" "/usr/local/var/app1"
Alias "/app2" "/usr/local/var/app2"

<VirtualHost *:80>
   # rewriting rules to make the routing work
   # There is only one vhost so it can actually be removed
</VirtualHost>

Когда мы обращаемся к https://sub.domain.com/app1, мы ожидаем перейти к app1. Когда мы обращаемся к https://sub.domain.com/app1.stg, мы ожидаемперейти на app1.stg

Приложения написаны на PHP. Эта конфигурация сервера означает, что мы должны включить «путь к приложению» в маршруты и переписать правила и использовать «полный абсолютный путь» во всех ссылках на ресурсы. Например, маршрут будет выглядеть так:

$router->map("GET", "/app1/action", SomeController);

Ссылка на css будет такой: (даже если указан относительный путь, он ведет себя так же, как относительный путь к DocRoot (с "/" впереди). Вы можете увидеть это в этом подробном посте )

<link href="app1/public/css/style.css" type="text/css" rel="stylesheet"/>

Этого будет достаточно, чтобы оба приложения работали, но промежуточная версия не будет работать, потому что она содержит ТОЧНО ОДНО ЖЕкопия кода (как это и должно быть, чтобы протестировать в промежуточной среде, а затем отправить в производственную среду). Если я хочу, чтобы обе версии работали, я должен динамически кодировать пути, а именно с помощью CONTEXT_DOCUMENT_ROOT или какой-либо другой серверной переменной, чтобы выяснить, в какой версии приложения она находится, и иметь две копии маршрутов, одна из которых начинается с app1, другая app1.stg,У меня также должно быть отдельное правило переписывания для каждой версии.

ВОПРОС

С примененным ограничением настройки сервера (одно доменное имя, различайте приложения в соответствии с тем, как я описал и т. Д.),Можно ли использовать только относительные пути, писать маршруты с соответствующими только для самого приложения? Например:

<link href="css/style.css" type="text/css" rel="stylesheet"/>

$router->map("GET", "/action", SomeController);

Другими словами, мне нужно изменить настройки сервера в рамках ограничений, чтобы приложение могло быть написано так, чтобы не заботиться о настройке сервера.

Я знаю, что один способ - использовать разные порты для каждого приложения / версии, но, очевидно, администратору сервера идея не нравится.

Я разбил проблему на этапы в этого вопроса. Это довольно долго, но если вы готовы выполнить, он должен предоставить гораздо больше деталей.


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


Итак, я понимаю, что у нас может быть несколько имен хостов в / etc / hosts, привязанных к одному IP-адресу. Могу ли я просто использовать это имя хоста в качестве имени сервера в конфигурации Apache и получить доступ в браузере, введя это имя хоста? Веб-сайт предназначен для внутреннего использования, поэтому доступ к нему должен осуществляться только в сети компании.

В / etc / hosts:

123.45.67.89 app1.team-server-name app2.team-server-name

В httpd.conf:

<VirtualHost>
    ServerName app1.team-server-name
    DocumentRoot /usr/local/var/app1/public
</VirtualHost>
<VirtualHost>
    ServerName app2.team-server-name
    DocumentRoot /usr/local/var/app2/public
</VirtualHost>

Ответы [ 2 ]

1 голос
/ 09 ноября 2019

Это довольно длинный вопрос, спасибо, что предоставили так много деталей.

Я бы выбрал другой подход, чем вы в настоящее время пытаетесь. Вместо того, чтобы пытаться обслуживать каждое из этих приложений из папки, настройте каждое из них как vhost на основе домена. Используйте что-то вроде app1.local или что-то еще для имени хоста и обязательно добавьте записи в ваш файл / etc / hosts под 127.0.0.1. Убедитесь, что директива listen для этих vhosts находится в loopback (127.0.0.1:80). Каждое из этих приложений должно функционировать так, как если бы они были установлены в корне документа своего собственного сервера. Весь CSS должен предполагать, что он находится в 'css / style.css' относительно /.

Теперь, когда у вас есть все приложения, настроенные на обратную петлю, вы можете настроить обратный прокси-сервер от vhost, слушающего на публикеинтерфейс для прокси всех расположений приложений к их соответствующему vhost loopback после удаления префикса / app1 из запроса.

Я не использовал Apache 2.x в течение очень долгого времени, но концепциитак же, как nginx.

location  /foo {
  rewrite /foo/(.*) /$1  break;
  proxy_pass         http://app1.local;
  proxy_redirect     off;
  proxy_set_header   Host $host;
}

Самая большая проблема с этим подходом заключается в том, что проксируемым приложениям либо нужно везде использовать относительные пути, либо им нужен какой-то настраиваемый префикс, который добавляется передURLs. Большинство фреймворков будут поддерживать опцию префикса. Например: https://laravel.com/docs/5.6/urls Этот префикс также может использоваться для загрузки ресурсов (css / js / jpg), но только из файлов, которые выполняют PHP.

0 голосов
/ 11 ноября 2019

В итоге я нашел решение с одним компромиссом.

DocumentRoot "/usr/local/var/www"
Alias /app1 /usr/local/var/app1/public

<Directory "/usr/local/var/www">
    RewriteEngine On
    RewriteRule ^/?$ /app1/ [R,L]
    RewriteRule (.*) /app1/$1 [R,L]
</Directory>

<VirtualHost *:80>
    <Directory "/usr/local/var/app1">
        Require all granted
        RewriteEngine On
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        # calls index.php (REQUEST_URI is still the same as before)
        RewriteRule ^ index.php [L]
    </Directory>
</VirtualHost>

Все относительные пути можно переписать обычным образом. Маршруты и запросы должны начинаться с имени приложения.

$router->map("GET", "/app1/hello2", SomeController);
// navigation bar. URI for another tab:
<li><a href="/app1/hello2">Hello 2</a></li>

Если мы хотим иметь несколько версий приложения, главное, чтобы узнать, в какой версии мы находимся, чтобы приложение могло отправитьправильный запросЭто можно сделать, проверив REQUEST_URI и запомнив, какая версия вызывается при вызове index.php. Затем в запросе (например, navigation src) добавьте его перед действием.

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

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

...