RESTful API - быстрый старт.

Статья — продолжение цикла, рассматривающего создание REST API для MODX со всех сторон.
Часть первая — введение

Рассмотрим как работает встроенный в MODX модуль для RESTful API, настроим первое подключение, разберем базовые моменты.



Первый запуск встроенного в MODX еще со времен версии 2.3. REST модуля — происходит довольно быстро и просто. Буквально в три шага.

Шаг 1
В корне проекта создаем новый каталог с произвольным именем. Лучше конечно использовать осмысленное имя. К примеру rest/
В каталог добавляем один единственный файл index.php. В нем подключаем сам MODX и несколько строчек для конфигурирования и вызова нашего модуля

// Подключаем MODX
require_once dirname(dirname(__FILE__)) . '/config.core.php';
require_once MODX_CORE_PATH . 'model/modx/modx.class.php';
$modx = new modX();
$modx->initialize('web');
$modx->getService('error', 'error.modError', '', '');


// Подготовим  некоторую базовую конфигурацию и загрузим класс modRestService
$rest = $modx->getService('rest', 'rest.modRestService', '', array(
    'basePath' => dirname(__FILE__) . '/Controllers/',
    'controllerClassSeparator' => '',
    'controllerClassPrefix' => 'MyController',
    'xmlRootNode' => 'response',
));


// обрабатывем запрос и возвроащаем ответ
/** @var modRestService $rest */
$rest->prepare();
// Проверяем, что пользователю предоставлены необходимые права доступа;
// Бьем по рукам и Возвращаем пользователю ошибку 401 ежели чего
if (!$rest->checkPermissions()) {
    $rest->sendUnauthorized(true);
}

$rest->process();
Шаг 2
Конфигурируем сервер. То есть объясняем что при обращении по адресу /rest/**/** нужно всего навсего вырезать все что стоит после /rest/ и передать в качестве параметра в файл index.php

Apache:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-s
RewriteRule ^(.*)$ rest/index.php?_rest=$1 [QSA,NC,L]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.*)$ rest/index.php [QSA,NC,L]

NGINX:
location /rest/ {
   try_files $uri @modx_rest;
}
location @modx_rest {
   rewrite ^/rest/(.*)$ /rest/index.php?_rest=$1&$args last;
}
После этого уже можно проверить работу модуля.
Для этого обращаемся по адресу /rest/любая_произвольная_строка
Если мы все сделали правильно — то модуль REST подхватит нашу произвольную строку в запросе, попытается найти у себя соответствующий контроллер, которого конечно нет и выдаст специфическую ошибку.



Модуль REST по умолчанию отдает все ответы в сыром JSON формате. Вы знали что Firefox умеет сразу красиво форматировать JSON и показывать его в удобном, отлично читаемом виде? Рекомендую для тестов использовать его.
Сравните как воспроизводят одну и ту же JSON строку Chrome (просто фу!)


и Firefox


Шаг 3
Получаем реальные данные из MODX.
На этом шаге нам понадобится создать дополнительный каталог с контроллерами.
Контроллеры — это классы, каждый из которых отвечает за отдельную таблицу MODX и соотвественно за группу запросов.

К примеру
Хотите работать с ресурсами?
  • Получить список ресурсов
  • Получить информацию по конкретному ресурсу
  • Добавить новый ресурс
  • Изменить существующий ресурс
  • Удалить ресурс
Создаем условный контроллер Resources.php, который будет отлавливать все запросы направленные по адресу /rest/resources/

Хотите работать с юзерами
Создаем условный контроллер Users.php который будет отлавливать все запросы направленные по адресу /rest/users/

В общем принцип такой — отдельная таблица (сущность) — отдельный контроллер. Хотя никто конечно не мешает подключать в классе и другие таблицы или даже целые компоненты, оперируя данными из них.

Что нужно знать про контроллеры
Класс modRestService, который определяет какой контроллер вызвать — предполагает несколько правил.
  1. Все контроллеры располагаются в определенном, заранее указанном в классе каталоге. Предсказуемо — именуем каталог Controllers
  2. Имя каждого контроллера равно запросу. Как я писал выше — для ресурсов это будет запрос /rest/resources/
    и файл Resources.php, для пользователей /rest/users/ и файл Users.php.
  3. Каждый контроллер это класс, расширяющий родительский класс modRestController. Мы также обязаны задать определенное имя класса. Оно формируется из двух обязательных частей. Префикс, общий для всех контроллеров + именование контроллера. Префикс задается в первоначальном вызове класса modRestController в index.php.
    Указав общий префикс MyController, мы получим следующие классы
    — class MyControllerResources extends modRestController
    — class MyControllerUsers extends modRestController
Вернемся к первому шагу и вспомним вызов класса modRestService
// Подготовим  некоторую базовую конфигурацию и загрузим класс modRestService
$rest = $modx->getService('rest', 'rest.modRestService', '', array(
    //Указываем имя каталога с контроллерами
    'basePath' => dirname(__FILE__) . '/Controllers/',
    'controllerClassSeparator' => '',
    //Указываем префис для именования классов контроллеров
    'controllerClassPrefix' => 'MyController',
    'xmlRootNode' => 'response',
));

Что должно быть внутри каждого контроллера

Классы modRestController достаточно автономны и не требуют особой настройки. Работают сразу, практикески из коробки. Достаточно указать лишь класс, с которым мы будем работать и по какому полю сортировать выдачу.
На этом все.

Вот так выглядят два моих класса для работы:
с ресурсами


с пользователями


Все — этого достаточно. Остальная работа происходит под капотом в родительском классе.

Естественно это довольно примитивные абстрактные примеры. В продолжении мы сделаем реальное API для действующего интернет-магазина, рассмотрим на практике подводные камни и нюансы, поговорим об инструментарии.
Николай Савин
29 сентября 2019, 08:01
modx.pro
11
1 610
+22
Поблагодарить автора Отправить деньги

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

Сергей
29 сентября 2019, 10:13
+1
Было бы интересно, если бы кто — нибудь рассказал, как во встроенном API обстоят дела с token-авторизацией
    Николай Савин
    29 сентября 2019, 10:27
    +1
    Про авторизацию и права еще поговорим
      Raimei
      21 июня 2021, 22:58
      0
      Интересует данный момент. Могу многое сделать кроме авторизации в MODX REST.
      Подскажите как одолеть вопрос? Может есть заметки на эту тему.
        Николай Савин
        22 июня 2021, 13:41
        0
        Я сам не особо этот вопрос одолел.
        Дело в том что авторизация в MODX хранится в сессии, что делает достаточно сложным вопрос опознавания юзера, который обращается к сайту по API. Это нужно идентификатор сессии получать и подписывать каждый запрос, да еще и поднимать уже существующую сессию по присланному идентификатору. Я пока не осилил.
        Есть несколько путей попроще. Например jwt сессии когда все хранится на стороне клиента.
        Я вот по пути Laravel обычно иду. Делаю идентификатор пользователя, подписываю им запросы и при каждом запросе авторизую пользователя. Но тут тоже есть подводные камни. Авторизацию и права нужные вы получите а вот с другими компонентами использующими сессию в работе все также проблематично пользоваться. Тем же minishop2 с его сессионной корзиной.
          Raimei
          23 июня 2021, 17:22
          0
          Не могу не поделиться одним из вариантов.

          Авторизация происходит через обращение на вашсайт/rest/auth. В GET-запросе должны находиться username и password. Далее можно обращаться к вашсайт/rest/myPackage или посмотреть как в файле реализована обёртка с проверкой.

          Для меня пока хватит и этого. В будущем попробую прикрутить токен, благо реализаций полно для MODX.
            Николай Савин
            24 июня 2021, 10:30
            0
            С авторизацией понятно, этот вопрос как раз и не сложный.
            А что делать с аутентификацией при каждом последующем запросе?
              Алексей Соин
              24 июня 2021, 15:32
              0
              гет параметрами логин и пароль отправлять эт конечно круто)))



              Б — безопасность)
                Raimei
                24 июня 2021, 15:35
                0
                Я конечно такой себе программист, особенно с PHP/MODX, но прекрасно понимаю всю глупость отправки подобным способом.

                Учитывая отсутствие каких-либо внятных альтернатив — пойдет и такое. Мне был важен сам метод проверки с простейшим примером.
        Сергей Шлоков
        29 сентября 2019, 18:07
        0
        Никак ни с токен-авторизацией, ни с какой другой. Есть всего один абстрактный контроллер, который нужно наследовать. Поэтому разработчику придётся всё писать самостоятельно.
          Сергей
          29 сентября 2019, 18:56
          0
          ну вот я поэтому и пишу) много статей про разные встроенные REST-подобные фичи в последнее время, но до сути необходимых для полноценной работы нормального REST — подобного интерфейса никто не доходит в этих статьях.
            Сергей Шлоков
            29 сентября 2019, 19:56
            +1
            Возможно автор топика дальше раскроет тонкости проверки прав, но в этом топике не сделал акцент, что вот за этим
            // Проверяем, что пользователю предоставлены необходимые права доступа;
            // Бьем по рукам и Возвращаем пользователю ошибку 401 ежели чего
            if (!$rest->checkPermissions()) {
                $rest->sendUnauthorized(true);
            }
            ничего не стоит, хотя комментарий вселяет уверенность, что проверка есть. А если заглянуть в код этого метода, то увидим следующее
            public function checkPermissions() {
                return true;
            }
            Новички могут попасть.
              Николай Савин
              29 сентября 2019, 19:58
              0
              В данном случае я процитировал документацию. Вот прямо скопипастил код. Задача быстрого старта — показать самые самые основы. Практические жизненные примеры попробую описать дальше.
                Сергей
                29 сентября 2019, 20:02
                0
                Это так себе на самом деле REST — API, полноценным REST API modx его назвать сложновато
                  iWatchYouFromAfar
                  29 сентября 2019, 20:02
                  0
                  Наверное по этой причине Сергей и пишет rest api… :)
                    Сергей Шлоков
                    29 сентября 2019, 22:31
                    +3
                    REST — это архитектурный стиль. А RESTful API — это реализация этого стиля.
                    Правильно говорить именно RESTful API, но в народе уже прижилось неправильное название REST API.
                    Николай Савин
                    29 сентября 2019, 20:05
                    0
                    Опять же — я цитирую официальный источник. В документации написано RestFul APi. Понятное дело это не полноценное REST. Здесь всего то несколько глаголов поддерживаются из всего зоопарка — и то, насколько я понимаю происходит эмуляция, а не полноценная поддержка.
          Fidst
          03 декабря 2020, 10:56
          0
          Благодарю за статью!
            Николай Савин
            03 декабря 2020, 10:59
            0
            Странный вопрос. Конфигурирование сервера пишется в файле htaccess в корне проекта.
            Ровно там же, где находится управление ЧПУ.
              Fidst
              03 декабря 2020, 11:03
              0
              да)
                Fidst
                03 декабря 2020, 11:23
                0
                на шаге 2 у меня выводит текстом код из первого шага. И остальные страницы тоже его выводят.
                  Николай Савин
                  03 декабря 2020, 11:26
                  0
                  Мне кажется эта задача сложновата для вас. Может стоит привлечь более опытного разработчика?
                    Fidst
                    03 декабря 2020, 12:28
                    0
                    Если человек <php?> пропустил, это не значит, что он не ПРО.
                      Fidst
                      03 декабря 2020, 13:02
                      0
                      Только у меня на всех страницах это сообщение. На главной и прочих
                        Fidst
                        04 декабря 2020, 10:52
                        0
                        Решено. Надо в /rest создать .htaccess(копия корневого .htaccess) и туда вставить код из шага 2
              Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
              24