GitHub является одним из наиболее популярных платформ для хранения и управления кодом, но можно ли использовать его в качестве системы управления контентом (CMS)? Ответ — да, и это может быть очень эффективным решением.
Проблема дублирования контента
Развитие веб-сайтов часто требует динамического контента, такого как журнал изменений и дорожная карта. Обычно для этого создается административная панель, где контент вводится вручную. Однако это может привести к дублированию контента и открытию двери для человеческих ошибок. Если контент уже существует на GitHub, почему вводить его повторно?
Архитектура решения
Решение состоит в том, чтобы использовать GitHub в качестве CMS и синхронизировать контент с локальной базой данных с помощью веб-хуков. Архитектура выглядит следующим образом:
- GitHub (push или release событие) отправляет POST-запрос на сервер.
- Сервер проверяет подпись HMAC-256 и парсит payload.
- Сервер обновляет или удаляет строки в локальной базе данных.
- Веб-сайт читает данные из локальной базы данных при загрузке страницы.
Типы контента и стратегии синхронизации
В данном примере используются два типа контента: журнал изменений и дорожная карта. Для каждого типа контента используется своя стратегия синхронизации:
- Журнал изменений: синхронизируется инкрементально, т.е. вставляются, обновляются или удаляются записи по мере необходимости.
- Дорожная карта: синхронизируется полностью, т.е. все данные удаляются и вставляются заново при каждом обновлении.
Верификация подписи
Каждый веб-хук GitHub содержит заголовок X-Hub-Signature-256, который представляет собой HMAC-SHA256-хеш тела запроса, подписанный секретным ключом. Чтобы предотвратить подделку запросов, необходимо проверить подпись перед обработкой запроса. Это можно сделать с помощью функции verifySignature, которая сравнивает ожидаемую подпись с полученной.
Обработка пинга
GitHub отправляет пинг-событие при создании веб-хука. Необходимо обработать это событие, чтобы GitHub не отметил конечную точку как неудачную. Это можно сделать, проверив наличие ключа zen в payload и ответив на него соответствующим образом.
Реализация на практике
В примере веб-сайта PointArt эта функциональность реализована в HookController с помощью маршрутизатора. При получении запроса от GitHub сервер проверяет подпись, парсит payload и обновляет локальную базу данных. Веб-сайт затем читает данные из локальной базы данных при загрузке страницы, обеспечивая актуальность контента.