Сбылась мечта идиота: теперь на сайте работают комментарии без строчки кода на Джаваскрипте. Смотайте экран вниз, там форма. Требуется только имя и тело комментария. Ввели, отправили, и через некоторое время он появится в блоге.

Форма:

Экран возврата:

А что, мне нравится.

Расскажу, как это работает. В прошлый раз я перенес комментарии Disqus в репозиторий. Каждый комментарий — это файл формата YAML + markdown. В числе прочего он хранит ссылку на пост. Когда я собираю блог, в подвал каждой заметки подставляются ее комментарии.

Для приема комментариев я следую тому же принципу: чтобы они появились на сайте, нужно создать файл в репозитории. Теоретически любой может оформить pull request, но это сложно. Должен быть сервис, который преобразует ввод пользователя в pull request для блога. Этот сервис я написал и назвал blog-backend.

Сервис напоминает веб-приложение: оно принимает HTTP-запрос с формой. После прелюдии с валидацией перехожу к главному: интеграции с Гитхабом. Это оказалось не так-то просто. У Гитхаба уже три рестовых API, но ни одно не покрывает все возможности. Кроме REST есть убер-апишка на GraphQL — она-то мне и нужна.

Интеграция с GraphQL была нелегкой: это самобытный язык и вещь в себе. Если бы в текущем проекте не было GraphQL, я бы полез на стенку. Во-вторых, сложность процесса: чтобы сделать PR силами API, нужно четыре вызова:

  1. получить метаданные репозитория, в том числе последний коммит;
  2. создать ветку от этого коммита;
  3. сделать коммит в новую ветку;
  4. сделать PR.

Как по мне, апишка не консистентна: где-то на репозиторий ссылаешься по имени, а где-то по машинному ID, который приходит из метаданных. То же самое с ветками: где-то имя, где-то айдишник. Ответы GraphQL развесистые, с глубокой вложенностью. Например, последний коммит ветки погружен на пять уровней:

(-> resp-get-repo :data :repository :ref :target :oid)

С такой апишкой невозможно программировать без образца данных.

Когда подружился с Гитхабом, настала проблема хостинга: где и как размещать логику. Мне понравился опыт с облаком Яндекса, и я продолжил эксперименты. Сервис написан на Кложе, скомпилирован Граалем в бинарь и хостится в Яндекс.Функции — аналоге AWS Lambda.

В свою очередь, Яндекс.Функция — это облачный сервис, где размещают какой-то код и дергают его по запросу. Отличие от обычного хостинга в том, что у лямбды нет состояния: она запускается на короткое время и умирает. В зависимости от окружения лямбда может умереть не сразу, и если ее дернуть повторно, сработает уже запущенный экземпляр. На базе этого делают “прогрев” лямбд, у которых окружение стартует медленно, например Java. В моем случае граальный бинарник быстрый как не весть что, прогрева ему не надо.

Лямбду можно вызывать разными способами, в том числе HTTP-запросом. У каждой лямбды свой урл, который может быть приватным и публичным. Его можно указать в разных сервисах, что отлично подходит для ботов.

По сравнению с VM-хостингом у лямбды следующие плюсы:

  • не нужна виртуальная машина и ее настройка;
  • не нужен домен;
  • лямбды экстремально дешевы, потому оплачивается только время работы с округлением до 0.1 секунды;
  • лямбды поощряют писать код без компонентов и состояния, что как бальзам на душу после проектов по работе.

Поначалу я был крайне скептичен к лямбдам, но теперь вижу в них особую прелесть. Единственный момент — пришлось написать код, чтобы подружить Кложу и Ring с окружением лямбды. Также поправил компиляцию Граалем, чтобы в бинарнике была верная кодировка. В будущем я планирую вынести код Яндекс.Облака в отдельную библиотеку, чтобы избавиться от копипасты.

Форма поддерживает синтаксис Markdown. Пока что нет кнопок выделения текста болдом и италиком, сделаю потом. Форма отправляется чистым POST, никаких аяксов, хотя первую версию я сделал на fetch, JSON и CORS. Про CORS я все забыл, и пришлось читать свою же статью о том, как все настроить.

Новые комментарии совмещают модерацию. После отправки создается PR в блог, мне приходит письмо, а пользователь переходит на прошлую страницу. Если все в порядке, я мерджу ветку и заливаю свежий билд блога. Таким образом, с момента публикации комментария может пройти от пяти минут до нескольких дней, но это ничего.

Первые комментарии я получил от кого? Правильно, от спамеров. Этим утром предложили виагру, казино и просто левые ссылки. Вот ссылка на уже закрытый RP и его содержимое:

---
id: 1663659055173
is_spam: false
is_deleted: false
post: /bookshelf/
date: 2022-09-20 07:30:55 +0000
author_fullname: 'epiehuliqukib'
---

http://slkjfdf.net/ - Tatacatay <a href="http://slkjfdf.net/">Aebaluk</a>
lwk.wlgg.grishaev.me.mrq.mn http://slkjfdf.net/

Очевидно, нужно вводить капчу для защиты от ботов. Я рассматриваю это как новый вызов: как сделать капчу без Javascript в статичном блоге? Уже есть мыслишки, расскажу в четвертой части эпопеи.

Наконец, последний тезис — зачем вы это делаете, мистер Андерсон? Зачем эти отказы, костыли, превозможения? Ответ — потому что могу. Просто хочется экспериментов. Надоели тормозные сайты с JS, хочу маленький оазис в своем огороде.