Intellect Board Pro
Расширяемый движок форума с разделами разных типов
Объявление
Вышла версия 3.05 с фотогалереей и поддержкой PostgreSQL и SQLite.
Перейти к скачиванию
Привет, гость!

4X_Pro
4X_Pro
Основатель проекта

Есть поддержка протокола WebMention

В пятницу доделал поддержку протокола WebMention. Это один из протоколов IndieWeb, который используется для того, чтобы уведомить автора публикации о том, что на этот материал отреагировали на другом сайте, например, написали ответную статью или просто сделали репост с указанием первоисточнка. Работает он так: WebMention-клиент заходит на страницу с исходной публикацией, обнаруживает там на специальный URL для уведомлений (он называется Webmention endpoint), и делает на него самый обычный HTTP-запрос, в котором указан адрес исходной публикации и страницы с реакцией. WebMention-сервер проверяет наличие ссылки на странице с реакцией и в том или ином виде фиксирует это у себя.
Серверную часть WebMention я реализовал достаточно давно, ещё в 2021 году. Это было достаточно просто: добавил в stdforum отдельный метод action_webmention, который делает все необходимые проверки, и если они проходят, в соответствующей теме создаётся сообщение от пользователя System о том, что по такому-то адресу упомянули наш материал. А в action topic_view добавил вывод тега link с rel="webmention" со ссылкой на этот action, для того, чтобы клиенты могли его обнаружить.
Клиентскую часть, на первый взгляд, тоже реализовать просто: при отправке сообщения выбрать в нём все ссылки, и для каждой сделать необходимый запрос. Сложности, как всегда, начинаются в деталях. В частности, в определении WebMention endpoint, куда нужно отправлять запрос (этот процесс называется endpoint discovery). Дело в том, протокол WebMention стремится к максимальной гибкости и допускает указание этого URL в разных местах: в HTTP-заголовках Link, в теге <link> в секции head и даже в обычной гиперссылке c тегом <a>, если для неё прописано rel="webmention". Чтобы надёжно находить такое в коде страниц, пришлось задействовать модуль dom. Но даже с этим модулем оказалось, что не всё так просто. Во-первых, в rel, кроме webmention, может быть что-то ещё, например, rel="webmention nofollow". Для корректной работы в таких ситуациях пришлось написать довольно сложное XPath-выражение:
//link[contains(concat(' ',normalize-space(@rel),' '),' webmention ')][@href]|//a[contains(concat(' ',normalize-space(@rel),' '),' webmention ')][@href]
Второй проблемой стало то, что ссылки могут быть как абсолютными URL, так и относительными (причём как от корня, так и от текущего каталога), и даже вовсе пустыми, и нужно обрабатывать все эти ситуации. Встроенных функций для работы с относительными URL в PHP почему-то нет, сторонние зависимости я стараюсь минимизировать, поэтому сделал своё решение.
И только после того, как всё перечисленное было сделано, удалось пройти все 23 теста на сайте webmention.rocks!
Кроме того, поскольку ссылок в сообщении может быть много, а запросы — дело достаточно долгое, есть шанс не успеть выполнить их все до окончания времени выполнения скрипта (того самого max_execution_time из настроек PHP). Поэтому для реализации клиента WebMention я впервые задействовал механизм taskов — одноразовых асинхронных задач, которые запускаются из скрипта cron.php после выполнения основных заданий. Но о них подробнее расскажу позже.

У вас нет прав для отправки комментариев.