# Протокол Gemini як альтернатива HTTP

Gemini - мережний протокол прикладного рівня, в своїй основі є спадкоємцем протоколу Gopher.

Орієнтований на мінімалізм та конфіденційність, оскільки виключає використання таких веб-технологій як Cookies та JavaScript, а формат даних, що передається - обмежений текстом або бінарними даними без підтримки стиснення та фонового завантаження зі сторонніх ресурсів. Обов'язковим є захист трафіку сертифікатом TLS.

Не зважаючи на простоту, протокол цілком багатофункціональний і дозволяє працювати з різними типами ресурсів: от як хостинг статичних файлів для персональних сторінок так і системи з авторизацією та обробкою запитів користувача - форуми, пошукові системи, організація радіо та відео стрімів, обмін зображеннями та іншими мультимедійними даними.

Враховуючи архітектуру, Gemini здебільшого буде цікавий тим, кого не влаштовує "роздутість" сучасного HTTP; стане в нагоді користувачам командного рядка, E-ink планшетів.

## Термінологія

Як і в багатьох екосистемах, для Gemini характерна своя термінологія, знання якої допоможе краще розуміти контекст і формувати пошукові запити:

* Gemini space - екосистема Gemini, подібно терміну "Fediverse" - для федеративної тематики
* Capsule - капсула, веб-сайт - назва протоколу походить від тематики космічної програми, тому багато проєктів наслідують концепцію у своїх назвах
* Gemlog - блог, персональна сторінка, фід профілю

## Розмітка

### Gemtext

Текстові ресурси gemtext - це звичайний текст (MIME text/gemini), схожий до Markdown, який опціонально містить наступні мета-теги на початку кожного рядка:

```
# h1
## h2
### h3

=> gemini://geminiprotocol.net 1965-01-19 Gemini

> цитата

* елемент списку 1
* елемент списку 2

` ` ` заголовок, назва файлу або розширення для підсвітки синтаксису (якщо підтримується)
код
` ` `
```

У розмітці Gemtext не використовуються декоративні технології накшталт CSS, при цьому завдання відображення ресурсу повністю делеговане клієнтові.

Різні браузери по-різному декорують вміст, деякі додають відступи.
Тому головний принцип створення крос-браузерних сторінок простий: розмітка має зручно читатися у вигляді початкового коду.

### Gemfeed

Оскільки текстовий регламент протоколу не передбачає використання мета-тегів, такі стандарти сповіщень як Atom та RSS, без зовнішніх засобів інтеграції, в Gemini - не застосовні.

Незважаючи на це, підписки можливі, зокрема - засобами стандарту Gemfeed для інтерпретації браузером змін документу Gemtext.
Наприклад, в браузері Lagrange, відстежувати оновлення сторінки можна за допомогою меню Bookmarks - Subscribe to page… і обрати відповідний сторінці спосіб - підписка при зміні заголовків на сторінці або за зміною дат у посиланнях.

Відстеження за датою посилань

У цьому підході здійснюється відстеження за датою, що вказана наступною за посиланням у форматі ISO 8601 (Y-m-d), наприклад:

```
# Заголовок сторінки виконує роль заголовка стрічки

Вміст параграфа ігнорується у відстеженні

=> /index.gmi будь-яке посилання, ігнорується

## Підрозділ сторінки, ігнорується

Довільний вміст підрозділу, що ігнорується

## Публікації

=> /pub1.gmi 2024-01-28 Посилання на першу публікацію - відстежується
=> /pub2.gmi 2024-01-29 Посилання на другу публікацію - відстежується
=> /pub3.gmi Посилання публікацію - не відстежується (оскільки не містить дати)
=> /pub4.gmi Посилання публікацію - не відстежується (оскільки дата є частиною заголовка і розташована зправа) 2024-01-30
```

Таким чином, документ не втрачає зручності для візуального сприйняття людиною і при цьому містить мета-інформацію, зрозумілу для програмного інтерпретатора в браузері, що відслідковує сторінку.

Єдиний недолік такого підходу полягає в тому, що оновлення не можна отримувати частіше ніж раз на добу. Як заявлено в документації, це пов'язано з часовими зонами.

Відстеження заголовків

Альтернативний підхід, який відстежує зміни у заголовках документу:

```
# Мій блог, заголовок стрічки

Параграф опису

## Перша публікація - відстежується

Опис першої публікації

=> /pub1.gmi Читати

## Друга публікація - відстежується

Опис другої публікації

=> /pub2.gmi Читати

...
```

## Коди статусів

Протокол Gemini має власний реєстр кодів заголовків, відмінний від типових для HTTP 200, 301, 404, 500, тощо

* 10-19 - input expected - очікується введення - використовується для відправлення та отримання даних форм
* 20-29 - success - код 20 аналогічний коду 200 в HTTP
* 30-39 - redirection - діапазон переадресації, у пакеті, що відправляється, код зазвичай супроводжується мета-посиланням: code + link + \n\r + text
* 40-49 - temporary failure
* 50-59 - permanent failure
* 60-69 - client certificates - у Gemini сертифікати використовуються для ідентифікації та авторизації користувачів

Клієнт зобов'язаний відхиляти будь-який код менше 10 або більше 69, при цьому повідомити користувача.
У невизначених випадках пріоритет буде відданий коду з початковим значенням діапазону, наприклад, 10 для 11 або 20 для 27.

## Обробка запитів

Протокол передбачає обмін пакетами із заголовками довжиною максимум 1024 байт. У цю довжину необхідно вмістити мета інформацію про пакет - наприклад рядок URI та/або дані введення користувача.

Текстові дані мають бути закодовані у стандарт RFC 3986 (відомий такими функціями, як urlencode). Якоюсь мірою це скорочує корисний обсяг заголовка при використанні наприклад кирилиці.

Тіло пакету складається із "сирих" текстових або бінарних даних без стиснення; сервер закриває з'єднання після надсилання останнього байту.

За допомогою статусів групи "10", що відправляються клієнту, сервер здатний запитувати введення користувача (замість звичних форм, у браузерах Gemini - це спливаюче текстове вікно)
Після отримання та обробки даних, сервер зазвичай повертає статус "20", статус "51" (не знайдено) або переадресацію на цільову сторінку з кодом "30".

Приклад запиту головної сторінки `gemini.circumlunar.space` для командного рядка:
``` bash
echo -e "gemini://gemini.circumlunar.space:1965/\r\n" | openssl s_client -connect gemini.circumlunar.space:1965 -ign_eof
```

Приклад умовної відповіді сервера з текстом "Hello World":
```
20 text/gemini; charset=utf-8; lang=en\r\nHello world
```

## Клієнт

Щоб відкрити ресурс з адресою `gemini://` потрібен спеціальний браузер, що стандартно працює з портом `1965`

Користувачі GUI можуть почати з популярних Lagrange, Eva, Kristall, Castor і т.д.

Що варто знати:

* Оскільки більшість клієнтів повертають одно-текстове рядкове поле запиту, додати новий рядок можна комбінацією клавіш Shift+Enter. Розширити спосіб введення можна за допомогою суміжного протоколу Titan, але розляд цього способу вартує окремого матеріалу.
* У протоколі Gemini немає webstorage та cookies, тому деякі інтерактивні сайти для функцій авторизації використовують сертифікати, які також можуть використовуватись для швидкої зміни облікового запису в браузері.
* Замість фідів RSS є вбудовані в браузер інструменти відстеження контенту (див. Gemfeed)

## Сервер

Поняття "сервер" у середовищі Gemini може бути не звичним для користувачів веб, які звикли до поширених веб проксі Nginx або Apache "на всі випадки". Термін часто передбачає повноцінний сервіс для конкретного завдання, що резервує за собою окремий системний хост і порт.

У каталозі "awesome-gemini" представлено велику кількість таких рішень:

=> https://github.com/kr1sp1n/awesome-gemini

Наприклад, для запуску простої статики підійде сервер Agate (Rust). При цьому назва звичного index.html залежатиме від обраного рішення, для Agate - це index.gmi але для іншого серверу постфікс може відрізнятись.

Запуск динамічних ресурсів часто передбачає розробку власного сокет-серверу для реалізації специфіки окремо взятої програми.

Веб-розробникам простіше зрозуміти принцип роботи "server-side" на прикладі декількох файлів gemini-php:

=> https://github.com/eapl-gemugami/gemini-php

Утім, в нових проєктах краще використовувати більш актуальні рішення, наприклад, з простих - форк бібліотеки Titan-II:

=> https://github.com/YGGverse/titan-II

Приклади реалізації можна подивитись у коді β-Doku - Gemini-проксі для DokuWiki:

=> https://github.com/YGGverse/bdoku

Щоб запускати різні сервіси на одному IP (не змінюючи стандартний порт), зручно встановити загальний проксі-сервер, який здійснюватиме маршрутизацію запитів на відповідну адресу/інтерфейс або на зовнішній сервер.

Якщо в HTTP - це Apache / Nginx, то для протоколу Gemini підійдуть Gmid (C):

=> https://gmid.omarpolo.com/

або Twins (Go):

=> https://code.rocket9labs.com/tslocum/twins

З другим помічені деякі проблеми з передачею довгих текстів, тому для початківців, бажано розпочати роботу з Gmid, який наразі активно розвивається та має дружній фідбек від розробника.

## З чого почати

=> gemini://geminiprotocol.net Домашня сторінка проєкту
=> gemini://geminispace.info Одна з пошукових систем
=> gemini://tlgs.one Ще одна пошукова система
=> gemini://chat.mozz.us Чат в режимі онлайн стріму (хороший тест для вашого клієнта)
=> gemini://bbs.geminispace.org Дошка оголошень і тематичні форуми
=> gemini://station.martinrue.com Соціальна мережа за типом twitter
=> gemini://hd.206267.xyz Офіційний Fediverse інстанс від розробників Tootik
=> gemini://meadow.hmmm.zt.ua Україномовний інстанс Tootik
=> gemini://gemlog.blue Найпростіший спосіб опублікувати свої сторінки в мережі Gemini
=> gemini://cities.yesterweb.org Хостинг з піддоменом, підтримкою Titan і WebDAV
=> gemini://flounder.online Хостинг з агрегатором останніх записів, є SFTP
=> gemini://astrobotany.mozz.us ASCII гра з догляду за рослинами, що затягує :)

## Схожі протоколи

* Gopher
* Guppy
* Nex
* Scorpion
* Scroll
* Spartan
* Text

## Дивіться також

=> gmid-server-for-gemini-protocol.gmi Gmid - багатофункціональний сервер для Gemini
=> nex-lightweight-gemini-alternative.gmi Протокол NEX - легка альтернатива Gemini
=> ukrainian-geminispace.gmi Український Geminispace