Обрабатывать несколько версий в одном URL

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

Цель состоит в том, чтобы иметь как "стабильную", так и "бета-версию" веб-приложения и позволить пользователям опробовать новые функции, не навязывая им (и их ошибкам) ​​их.

Теперь очень простой способ сделать это - поместить каждую версию в отдельную подпапку, например www.mywebapp.com/v1 и www.mywebapp.com/v2.

Однако мне бы хотелось, чтобы это было прозрачно для пользователя, а URL веб-приложения оставался неизменным (например, www.mywebapp.com/).

Какая версия должна быть загружена, определяется на стороне сервера после входа пользователя в систему (например, активная версия для данного пользователя сохраняется в БД) и может быть позднее изменена, когда пользователь нажимает на кнопку "попробовать новую версию"/"go вернуться к старой версии "ссылки.

На стороне сервера я должен обойтись MySQL, PHP и Apache.

Мне уже удалось заставить это работать, помещая каждую версию в свою собственную подпапку, затем сохраняя информацию о версии в файлах cookie (обновляемых сервером при каждом входе в систему или при обновлении страницы) и используя RewriteRule(s) для "прокси" запросов от базы / версии. URL к соответствующей подпапке. Если cookie не установлен, папка по умолчанию выбирается резервным RewriteRule.

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

Спасибо!

7 ответов

htaccess позволяет переписывать на основе содержимого файлов cookie. Поскольку Apache является УДИВИТЕЛЬНЫМ в перенаправлениях, а PHP адекватен, я бы справился с этим.

В этом примере проверяется, есть ли файл cookie версии. Если есть, он добавляет 'vers=' + все, что было в куки верс, к запросу.

RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_COOKIE} vers=([^;]+) [NC]
RewriteRule ^(.*)$ /$1?vers=%1 [NC,L,QSA]

(этот пример можно найти здесь)

Я думаю, что лучшим способом в PHP было бы просто запросить базу данных, получить нужную версию, а затем include() это из подпапки. Таким образом, это прозрачно для пользователя.

Например, предполагая, что пользователь выбрал новую бета-версию, вы сохраняете его запись в базе данных,

UPDATE `versions_table` SET (`version`) VALUES ('1.02b') WHERE `userid` = 5

И затем, когда он заходит на страницу, у вас происходит что-то вроде этого:

//PDO Connection here, skipped for example purposes
$stmt = $pdo->query('SELECT `version` from `versions_table` WHERE `userid` = 5 LIMIT 1'); 
//Of course 5 is only an example, in actual code that would be a variable
//representing the actual user ID.
$row = $stmt->fetch(); //Should be only one row.
include_once($row['version'].'/myApp'.'.php'); //Include 1.02b/myApp.php

Используйте один RewriteRule для перенаправления всех запросов на один route.php файл в корневой папке вашего сайта.

route.php файл должен выглядеть так:

$user = authenticateUser();
$version = $user->getPreferredVersion();

$filePath = $_SERVER['DOCUMENT_ROOT'].'v'.$version.$_SERVER['REQUEST_URI'];

if( !file_exists( $filePath ) ) {
    header("Status: 404 Not Found", true, 404 );
    die();
}

$pathDetails = pathinfo( $filePath );

if( $pathDetails['extension'] == 'php' ) {
    require( $filePath );
} else {
    if( $pathDetails['extension'] == 'jpg' ) {
        header( 'Content-Type: image/jpeg' );
    } elseif( $pathDetails['extension'] == 'gif' ) {
        ...
    } elseif (...) {
        ...
    } else {
        // unsupported file type
        header("Status: 404 Not Found", true, 404 );
        die();
    }
    echo file_get_contents( $filePath );
}

Это план того, что вы должны делать в route.php В этом файле вы должны позаботиться о некоторых других технических и технических проблемах безопасности.

Это может помочь: то, что я использую в течение месяца,

  1. Сохраните все файлы в базе данных (путь, код, версия = десятичное число (3,1), флаг: стабильный = 3 / lab = 2 / beta = 1 / alpha = 0)

  2. have.htaccess перенаправляет все несуществующие файлы (не перенаправляет изображения, css, js или другие статические файлы без версии) внутренне в loader.pm (для вас loader.ph_) не использует то же расширение, что и другие ваши файлы для дифференциация

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^   loader.pm [L,QSA]
    
  3. Загрузчик загружает последнюю стабильную версию из базы данных или бета-версии, если стабильной версии не существует.

    SELECT code, version, flag FROM table WHERE path = ? AND flag > 0 ORDER BY flag DESC, version DESC LIMIT 1 Не показывать альфа-страницы, находящиеся в разработке

    вывести ошибку 404, если нет результатов, и

    когда указана версия как ?v=2.0 файл загрузчика использует другой запрос

    SELECT code, version, flag FROM table WHERE path = ? AND version <= ? ORDER BY flag DESC LIMIT 1

Предположения:

  1. Пользователь либо хочет стабильный или последний; так что вам на самом деле не нужно больше 2 файлов на путь; пока, если вы не хотите сохранить старые версии для демонстрации. Если пользователь хочет последний, используйте .. ORDER BY version DESC, flag DESC, ..
  2. Пользователю не важно знать, какая это версия, поэтому вместо того, чтобы устанавливать одну и ту же версию сразу для всего сайта, мы устанавливаем версию каждого файла отдельно; так что отслеживание разработки легко.

Проблемы:

  • Нет индекса / первичного ключа
    • Вы должны убедиться, что у вас нет повторяющихся записей, хотя это не сломает ваш сайт, но не будет хорошо выглядеть;)
    • если для файла существует такая же бета-версия и стабильная версия, а пользователь выбрал последнюю (бета-версию); тогда вы можете случайно доставить ему бета-файл вместо стабильного файла.
  • переменная строки запроса ?v= зарезервировано для выбора версий, но это нормально; вы можете выбрать ?var=

Хотя для создания правил можно использовать механизм маршрутизации и информацию о сеансе, я бы предпочел оставить ваше текущее решение. Все, что вам нужно сделать, внедрив его в PHP, - это передать нагрузку с apache2 (у которого уже есть очень быстрый Rewrite-Engine) в бинарный файл php. Кроме того, вы рискуете помешать работе вашего приложения из-за несовместимости данных, файлов cookie и других переменных на основе сеанса.

С другой стороны, у вас есть преимущество повторного использования общих объектов, таких как библиотеки, доменные модели, преобразователи данных и т. Д. Но, на мой взгляд, это преимущество не влияет на худшую производительность и риск вмешательства.

Итак, в одной фразе, я считаю, что ваше текущее решение лучше.

Существует облачная платформа, которая делает это автоматически при развертывании. http://www.cycligent.com/
Это просто вопрос установки файла cookie после развертывания двух версий. Гораздо меньше работы, чем некоторые другие показанные ответы.
Полное раскрытие: я работаю на Cycligent.

Загрузите свою версию / страницу / страницу в IFRAME, и IFRAME src может быть "webapp.com/v2"..

Поэтому, какую бы версию пользователь ни выбрал, ваша адресная строка будет читать webapp.com, но ваш URL IFRAME постоянно меняется в зависимости от версии.

Нет необходимости писать правила перезаписи.

Другие вопросы по тегам