При использовании приложений, требующих от пользователя входа в систему перед использованием, пользователи иногда забывают сначала войти в систему и ввести URL-адрес ресурса в адресную строку. Затем они перенаправляются на страницу входа. Иногда после успешного входа в систему им приходится снова вводить URL-адрес страницы, которую они хотели посетить. Это не обеспечивает хорошего пользовательского опыта. Пользователь на какое-то время теряется, ругается на вас и клянется никогда больше не посещать ваш сайт. Лучше было бы перенаправить пользователя на страницу, которую он хотел посетить, прежде чем он будет перенаправлен на страницу входа. Некоторые люди называют такое поведение дружественной переадресацией.

Проблема

Я хотел реализовать эту функцию в приложении, которое я создаю (на момент написания этого поста), и, будучи новичком в Meteor, я не имел ни малейшего представления о том, как это сделать. На ум пришли две идеи; используя «объект запроса» (что является чуждым понятием в Meteor) и используя систему маршрутизации. Первый вариант был отброшен, потому что это невозможно сделать.

Использование FlowRouter

Я использую маршрутизатор Kadira FlowRouter, поэтому я покопался в его руководстве по маршрутизации здесь. В документации описывается концепция, называемая триггерами, которая дала мне понять, что я смогу решить свою проблему, используя эту концепцию. Приведенный в документации пример, отдаленно напоминающий функцию, которую я хотел реализовать, называется Old Route Redirection. Этот пример действительно демонстрирует, как перенаправить на новый маршрут. Но как мне получить маршрут, который хотел посетить пользователь? Потребовалось дополнительное чтение документации. Я читал документацию FlowRouter на Github. Под заголовком API я нашел функцию FlowRouter.current(), которая возвращает текущее состояние маршрутизатора. Мне это показалось интересным, поэтому я решил копнуть глубже. Эта функция возвращает объект со свойством oldRoute.

Эврика!

Поиграв некоторое время с функцией FlowRouter.current(), я убедился, что oldRoute — это то, что мне нужно. Его значение хранит маршрут, с которого пользователь пришел на текущий маршрут. Если пользователь не был перенаправлен ни с одной страницы, значение oldRoute не определено. Таким образом, сохранение значения этого свойства приблизило бы меня к решению, которое я искал. Кроме того, я знал, что, возможно, смогу объединить это с триггерами FlowRouter.

Триггеры FlowRouter

Триггеры, как описано в документации, похожи на промежуточное ПО Express.js, которое запускается на определенных этапах процесса маршрутизации. triggersEnter запускается при входе в маршрут, а triggersExit запускается при выходе из маршрута. Обе функции могут иметь до трех аргументов. Оказывается, первый аргумент возвращает объект, идентичный возвращаемому значению FlowRouter.current(). Второй аргумент — это функция перенаправления, которую можно использовать для перенаправления на другой маршрут. Обратный вызов маршрута можно остановить, используя третий аргумент, stop. Собрав все эти части воедино, я был близок к решению своей проблемы.

Демонстрация сценария

Предположим, я хочу посетить маршрут /products, но для этого сначала требуется выполнить вход. Если я наберу http://localhost:3000/products, меня немедленно перенаправят на страницу входа (маршрут /signin). Я хочу, чтобы после успешного входа меня перенаправляли на /products. Вот как мой входной маршрутизатор был определен для достижения этой цели:

FlowRouter.route(‘/signin’, {
 triggersEnter: function(params) {
   if (Meteor.userId()){
     FlowRouter.go(‘/home’);
   }
 },
 triggersExit: function(params, redirect) {
   let destinationRoute = params.oldRoute;
   if (destinationRoute) {
     let destination = destinationRoute.path;
     if (destination !== undefined || destination !== ‘/’) {
       redirect(destination);
     }
   }
 },
 name: ‘Signin’,
 action() {
   BlazeLayout.render(‘application’, {
     nav:    ‘nav’,
     main:   ‘signin’,
     footer: ‘footer’
   });
 },
});

Как видно из приведенного выше кода, если пользователь уже вошел в систему, он перенаправляется на маршрут «/home». Однако если пользователь перенаправляется на маршрут входа с другого маршрута, params.oldRoute будет содержать «/products» — маршрут, с которого был перенаправлен пользователь.

Вот такую ​​дружественную переадресацию в Meteor придумал я!

Хотя реализовать дружественную переадресацию в Meteor с помощью Kadira FlowRouter очень просто, если вы знаете, как работают триггеры, документация по триггерам кратка. Это немного затрудняет понимание возможных вариантов его использования новичком в Meteor.

Комментарии и/или предложения по улучшению будут очень признательны.