В теме, посвященной «новым» браузерам, я упомянул недостатки протоколов Gemini и его упрощенного аналога Spartan. Представляю вашему вниманию еще один протокол, сделанный на коленке на основе вышеуказанных протоколов. Я ни на что не претендую и делаю это в качестве развлечения. Итак, я взял описание протокола Spartan и несколько подправил его. Протоколу дано временное название owl, чтобы обозначить его в ссылках. Временное - потому что с таким названием есть нечто, относящееся к NFT, а также игровой движок. И вот результат:
Описание протокола
1. Обзор
Протокол Owl - прикладной протокол передачи данных, попытка собрать нечто среднее из протоколов Gemini и Spartan. В качестве фундамента для Owl использован протокол Spartan.
Протокол использует для передачи данных TCP, и является текстовым. Подобно Gemini, Owl может использовать для шифрования TLS с схемой аутентификации TOFU и поддерживает пользовательские сертификаты для аутентификации. Как и в случае Spartan, для Owl в документах gemtext допустимо использование строки "=:" для пользовательского ввода, а также Owl имеет сходную модель запросов.
Owl использует 5 видов статусов в ответе на запрос: "Успешно выполненный запрос", "Перенаправление", "Ошибка сервера", "Ошибка клиента", "Необходимость в сертификате клиента".
Если шифрование не используется, то в URL протокол указывается как owlet://
Стандартный порт для owl - 288, для owlet - 289. Протокол является синхронным, в ответ на запрос клиента сервер передает ответ, после чего при статусе ответа "Успешно выполненный запрос" клиент передает данные (при их наличии), затем данные передает сервер (при их наличии).
2. Запросы.
Запрос клиента к серверу в Owl представляет собой строку текста в кодировке UTF-8, которая предстает в следующем виде
URL [символ горизонтальной табуляции] [опциональный блок, используемый для получения части данных] [размер блока данных в байтах] CRLF [блок данных - передается серверу после получения ответа со статусом успешно выполненного запроса]
[опциональный блок, используемый для получения части данных] = [диапазон в байтах в виде двух чисел разделенных символом "дефис" или числа и символа точки][символ пробела]
Блок данных в конце запроса является опциональным, при его отсутствии размер блока данных должен быть указан как "0". Тип данных может быть как бинарным, так и текстовым или смешанным. Клиент не указывает тип данных, сервер должен сам его определить исходя из контекста.
Порт в url указывается, если он отличается от порта по умолчанию. Размер запроса без данных не должен превышать 1024 байт.
Примеры запросов:
-- Скачивание txt файла
owl://example.com/1.txt 0
-- Отправка данных серверу (комментарий к статье на русском языке)
клиент: owl://example.com/articles/1/comment 20
сервер: 2 gemini/text; lang=ru
клиент: Привет мир!
сервер: [текст статьи с комментариями]
-- Отправка данных серверу (комментарий к статье на английском языке)
клиент: owl://example.com/articles/1/comment 12
сервер: 2 gemini/text; lang=en
клиент: Hello world!
сервер: [текст статьи с комментариями]
--Отправка на сервер музыкального файла
клиент: owl://example.com/upload/music.ogg 1205328
сервер: 2 none 0
клиент: [бинарные данные]
--Запрос статьи от сервера, использующего нестандартный порт
owl://example.com:90/articles/1 0
Также клиент может запросить от сервера только часть данных, указав диапазон в байтах в виде двух чисел разделенных символом "дефис". Использовать символ точки вместо второго числа можно, если данные необходимо получить частично начиная с байта указанного первым числом и до конца данных.
Примеры запросов:
owl://example.com/music/spring.mp3 14721-872345 0
owl://example.com/music/spring.mp3 14721-. 0
3. Ответ на запрос
Ответ сервера состоит из одной строки в кодировке UTF-8 и имеет следующий вид:
-- Код ответа 2 - "Успешно выполненный запрос"
2 [символ горизонтальной табуляции] [тип данных] [дополнительный опциональный блок] CRLF [данные от сервера]
Дополнительный опциональный блок в ответе содержит символ горизонтальной табуляции и следующее за ним число, указывающее на размер данных от сервера в байтах.
Данные от сервера клиенту начинают передаваться после завершения получения данных от клиента, если таковые имеются.
Сервер может в некоторых ситуациях не передавать данные в ответ на запрос клиента. В этом случае ответ сервера будет выглядеть следующим образом:
сервер: 2 none 0
В этом случае соединение будет закрыто при завершении получения данных от клиента или сразу после ответа сервера при отсутствии клиентских данных.
-- Код ответа, начинающийся на 3 - "Перенаправление"
При этом код может быть расширен до 30 (Временное перенаправление) или 31 (Постоянное перенаправление), однако это не является обязательным. URL может быть как абсолютным, так и относительным по отношению к URL, использованным в запросе клиента.
3 [символ горизонтальной табуляции] URL CRLF
-- Код ответа, начинающийся на 4, указывает на ошибку клиента. Ответ содержит человекочитаемый текст, объясняющий характер ошибки.
4 [символ горизонтальной табуляции] [сообщение об ошибке] CRLF
--Код ответа, начинающийся на 5, указывает на ошибку сервера. Ответ содержит человекочитаемый текст, объясняющий характер ошибки.
5 [символ горизонтальной табуляции] [сообщение об ошибке] CRLF
--Код ответа, начинающийся на 6, указывает на необходимость в сертификате клиента (передается на этапе установления соединения с шифрованием в рамках протокола TLS), в этом случае клиент повторяет запрос, но предоставляет сертификат. Если клиент предоставил сертификат, но все равно получил этот ответ, это означает, что сертификат не был принят, в этом случае ответ может содержать человекочитаемый текст, объясняющий характер ошибки.
Код этой ошибки может быть получен только при использовании шифрования.
6 [символ горизонтальной табуляции] [при необходимости - сообщение об ошибке] CRLF
Примеры запросов и ответов на них
клиент: owl://example.com/helloworld.txt 0
сервер: 2 text/plain; charset=utf-8 12
сервер: Hello world!
owl://example.com/helloworld.txt 0
3 owl://example2.com/helloworld.txt
owl://example.com/helloworld.txt
4 Неправильно составлен запрос
owl://example.com/helloworld.txt 0
5 Внутренняя ошибка сервера
owl://example.com/helloworld.txt 0
6 Неверный сертификат
4. Формат документа.
Owl использует в качестве предпочтительного тот же формат документов, что и Spartan - модифицированный text\gemini.
В частности, от стандартного text/gemini формат документов Spartan отличается наличием дополнительной строки ":=" для ввода пользовательских данных. Вид вводимых данных (текст, файл) определяется клиентом.
=:[пробел]<URL>[пробел человекочитаемое представление ссылки]
5. URL
Структура URL для owl напоминает структуру URL для http.
scheme://userinfo@host:port/path;parameters?query#fragment
Согласно стандартам пробелы в URL должны быть представлены как "%20", однако протокол способен работать с "настоящим" пробелом, поэтому его появление в запросе не должно быть расценено как ошибка.
Соответствия URL запросам
owl://example.com => owl://example.com 0
owl://example.com/1 => owl://example.com/1 0
owl://example.com?a=1&b=2 =>
owl://example.com 7
a=1&b=2
owl://example.com/my%20file.txt =>
owl://example.com/my%20file.txt 0
Если вы дочитали до этого момента, то от вас требуется критика, пожелания, а возможно, свой вариант протокола. Воспринимайте данный протокол как нечто несерьезное, планов построить свою гипертекстовую сеть у меня нет. Что касается самого протокола, у меня есть сомнения в отношении правильности некоторых решений. Во-первых, в том как формируется запрос для получения части данных. Во-вторых, следует ли использовать табуляцию для разделения разных элементов в запросах и ответах. В третьих, как следует поступать с пробелом в URL.