Первая (и, возможно, последняя) запись дневника разработки yah2g

Я уже давно подумываю, что мне на сервере не хватает веб-прокси для Gemini. Иногда хочется иметь возможность дать ссылку на Gemini https URL'ом.

Всё, конечно, уже написано в этом мире за нас, поэтому для начала я обратился к списку известных веб-прокси для Gemini.

Список известных веб-прокси

Список оказался немного не актуальным: часть сервисов из списка уже не работают. Wobbly и построенные на его основе прокси требуют Javascript в веб браузере. (JS для просмотра простого текстового протокола? Извините, но это уже перебор). Самый симпатичным (мне) показался вариант Mozz.us portal:

SmolNet Portal

Но и он обладает двумя критическими недостатками:

Насчёт последнего, конечно, шутка. Дело вот в чём: я подумал, что нехорошо, что такой годный проект поднят в сети только в одном экземпляре, хорошо бы запустить копию у себя на сервере. Я даже был готов ради него в своём сервере vostok заменить пустые MIME на что-то вроде "text/gemini". Но потом я посмотрел на его исходный код:

https://github.com/michael-lazar/gemini-portal

И в репозитории я обнаружил, что с одной стороны там много всего, что мне вообще не нужно. А с другой - ради всего этого используется внушительный набор внешних зависимостей. А мы же все любим раскидистые зависимости в пайтон? И да, тут не самые широкие зависимости из тех, что я видел. Но ведь можно реализовать такой прокси сервер только на стандартной библиотеке пайтон? Я подумал, что можно, да и задача, вроде как, не сложная.

Значит, решено: пишем на пайтон в рамках стандартной библиотеки.

Для реализации HTTP сервера используем модули http и http.server

https://docs.python.org/3/library/http.html

https://docs.python.org/3/library/http.server.html

Для реализации gemini клиента используем модули socket и ssl

https://docs.python.org/3/library/socket.html

https://docs.python.org/3/library/ssl.html

И для клиента, и для сервера потребуются манипуляции с URL, а значит нужен модуль urllib.parse

https://docs.python.org/3/library/urllib.parse.html

А для формирования тела ответа (HTML) пригодится модуль xml.etree.ElementTree

https://docs.python.org/3/library/xml.etree.elementtree.html

Из всего этого я и собрал проект yah2g (yet another http-to-gemini). Git репозиторий с исходным кодом сервера можно клонировать по следующей ссылке:

ssh://anonymous@got.any-key.press/yah2g

Web интерфейс к git репозиторию

Мой экземпляр сервера запущен на OpenBSD. За SSL/TLS отвечает relayd, который перенаправляет HTTP запросы к запущенному python3, исполняющему скрипт yah2g.py.

https://gem.any-key.press/

По реализации стоит сделать несколько замечаний.

Прокси сервер, опираясь на MIME из ответа, различает два вида полученного из Gemini содержимого: text/gemini и всё остальное. Gemini страницы первого вида из text/gemini преобразуются в HTML. Конвертер получился несложный. К примеру текущая Gemini-страница доступна по следующей ссылке:

https://gem.any-key.press/?url=gemini%3A%2F%2Fany-key.press%2Fyah2g%2Freport_0.1.gmi

А все остальные виды содержимого отдаются HTTP ответом без преобразования. Это позволяет, например, смотреть картинки в сыром виде:

gemini://vostok.any-key.press/capsule/vostok.png

Или, в качестве другого примера, подписаться на atom.xml:

gemini://any-key.press/atom.xml

Второе замечание по реализации касается запроса пользовательского ввода в Gemini (статусы 1x). Сервер их на текущий момент не поддерживает. Честно говоря, и дорабатывать их поддержку я пока не планирую. Поэтому, например, заслать новую ссылку в geddit с помощью прокси сервера не получится (может это даже и хорошо).

Кстати, неплохой тестовой базой для проверки конвертации Gemini-разметки в HTML служила страница со спецификацией gemtext:

gemini://geminiprotocol.net/docs/gemtext-specification.gmi

Но стоит учитывать, что, например, строка цитаты там описана, но не представлена примером.

Для самопроверки я так же сделал несколько страниц, которые покрывают некоторые крайние случаи конвертации Gemini-разметки в HTML:

Тестовая страница, содержащая все типы строк

Тестовая страница, содержащая экранируемые в HTML символы

Тестовая страница, содержащая в последней строке элемент списка

Тестовая страница, содержащая в конце незакрытый блок преформатированного текста

Комментарии через ActivityPub (Fediverse) можно оставить здесь:

https://honk.any-key.press/u/continue/h/FC15XJT95Bdl61x3st

Следующая запись дневника разработки yah2g