freshgo 0.3.14: месяц спустя это уже не FreshRSS
В этой статье
Первый коммит freshgo сделан 6 октября. Задумывался он как порт FreshRSS на Go1, а к версии 0.3.9 в нём было уже много своего2. С тех пор вышли 0.3.10–0.3.13 и две предварительные версии 0.3.14, всего 39 коммитов. Сегодня вышла 0.3.14-rc.2, и на моём сервере работает уже она.
В этот раз я поставил FreshRSS 1.30.1 и freshgo рядом, на одних и тех же лентах, и снял одинаковые экраны в обоих. Данные в freshgo пришли из этого же FreshRSS командой freshgo import, так что статьи совпадают.
Что сделано сегодня
Все три изменения выросли из одного наблюдения: страница «Непрочитанные» открывалась чуть дольше секунды. Это мало, но задержку видно3.
Подготовка «Непрочитанных». Пока открыта другая страница, браузер заранее скачивает «Непрочитанные» и держит ответ в памяти. При переходе сервер всё равно проверяет вход и заново собирает страницу. Если она совпала с заготовленной, он отвечает 304 без тела, и браузер показывает то, что уже скачал. Если что-то изменилось, приходит обычный ответ. Заготовка одна, не больше 2 МиБ, живёт 15 секунд. На скрытой вкладке и при экономии трафика её не делают.
Замер шёл в Chrome на 250 непрочитанных статьях по 6 КБ, со связью, искусственно замедленной до 40 мс задержки и 1 МБ/с. Переход на «Непрочитанные» внутри читалки до готового кадра занимал 1108 мс, теперь 185 мс (медианы из пяти прогонов). Прямое открытие страницы по адресу не ускорилось: те же 898 КБ надо скачать. Теперь список появляется целиком, когда разобран, а не заполняется строками по мере загрузки.
Подгрузка следующей страницы. Раньше сто новых статей вставлялись в список по одной, теперь одним блоком, собранным вне документа. Время подгрузки от этого не изменилось, его по-прежнему определяет сеть. Меняется то, что список больше не растёт на глазах.
Две находки по дороге. Пока шла проверка, упали два теста, которые к изменению отношения не имели. Форма настроек ленты на экране шириной 360 точек уезжала вбок на 6 точек: блок с выбором значка не сжимался уже ширины своего поля для файла. Хватило одного свойства CSS, min-width: 04. Второй тест проверял, что разбор огромной ленты укладывается в 20 секунд, и падал, когда машина была занята другими тестами. Теперь он не смотрит на часы: разбирает документы двух размеров, восьмикратно отличающиеся, и сравнивает, во сколько раз выросли процессорное время и выделенная память. Больше 24 раз означает, что разбор стал квадратичным5.
Что появилось с 0.3.9
Вход по passkey. В профиле можно завести passkey для каждого устройства, и вход проходит по отпечатку, лицу или PIN-коду, без пароля и без кода из приложения. Администратор может отключить вход по паролю совсем. Пароли для приложений при этом продолжают работать, а freshgo user passwd для администратора включает вход по паролю обратно, если все passkeys потеряны.

Перевод для приложений. Перевод статьи языковой моделью был в веб-интерфейсе. Теперь его можно запросить и через Google Reader API, отдельным расширением по адресу /api/freshgo/translation. Перевод хранится на сервере, так что переведённая на телефоне статья в браузере уже переведена, и наоборот. Первым клиентом стал мой Android-клиент Brook. Уведомления о прочитанных и отмеченных статьях тоже теперь приходят в приложения, а не только в браузер.
Загрузки стали аккуратнее. Cookie, логин с паролем и дополнительные заголовки ленты уходят только на её собственный сайт, даже если статья или найденная на странице лента лежат на другом. Проверка адресов отсекает ещё несколько зарезервированных диапазонов IPv4 и IPv6. Адрес клиента из X-Forwarded-For теперь берётся справа, с пропуском своих прокси, и подделать его, дописав адрес слева, нельзя. Google Reader API отказывает пользователю без пароля для приложений: раньше его токен зависел только от соли установки6.
Мелочи:
- категория и метка с именем, отличающимся только регистром, больше не заводятся;
- форма ленты не сохраняет CSS-селектор или фильтр с ошибкой, а раньше ошибка всплывала только при обновлении;
- экспорт собирается во временном файле: на 3000 статей по 30 КБ память растёт на 43 МБ вместо 273 МБ;
- ссылки из текста статьи открываются в новой вкладке.
Чем freshgo теперь отличается от FreshRSS
Хранение, импорт, язык поиска и Google Reader API остались совместимыми, клиенты переезда не замечают. Всё остальное разошлось.
Чтение. FreshRSS показывает дерево лент слева и список с кнопками над ним. В freshgo дерево свёрнуто в шапку потока и открывается клавишей t, а строка статьи несёт ещё и начало текста.


Статья в freshgo раскрывается на месте, как в Google Reader. Действия стоят между заголовком и текстом: прочитано, полный текст, оригинал, перевод, пересказ, метки.


Телефон. FreshRSS на узком экране обрезает заголовки в одну строку. freshgo переносит их целиком, а внизу держит панель: предыдущая статья, прочитано, звёздочка, следующая.
Обновление лент. Во FreshRSS у ленты период обновления по умолчанию общий. freshgo опрашивает ленту так часто, как она публикует, учитывает Cache-Control и Expires её сервера и после сбоев ждёт дольше. На странице настроек ленты это пункт «Автоматически, по частоте публикаций».


На этом же стенде нашлось отличие, которого я не ждал. FreshRSS не прочитал ленту research.swtch.com: её сервер отдаёт документ с типом text/plain, и FreshRSS написал в журнал, что ленты по адресу нет. freshgo ту же ленту прочитал и забрал из неё 24 статьи.
Остальное, чего во FreshRSS нет, перечислю списком:
- полный текст статьи без CSS-селектора, по клавише
fдля одной статьи, через настоящий браузер для сайтов за проверкой Cloudflare; - перевод, пересказ и подсказки меток языковой моделью;
- картинки статей через сервер, чтобы их сайты не видели читателя;
- переходы без перезагрузки страницы и счётчики, которые обновляются сами, при этом всё работает и без JavaScript;
- палитра команд по
Ctrl+Kи управление с клавиатуры; - Web Push, ежедневное письмо с непрочитанным, сохранение в Linkding;
- второй фактор (TOTP), passkeys, вход через OpenID Connect;
- импорт из Miniflux и Tiny Tiny RSS, Fever API;
freshgo backup,restore -checkиdoctorдля того, кто держит сервер.
Что дальше
0.3.14 пока предварительная версия. Если за несколько дней на моём сервере ничего не всплывёт, она выйдет как обычная. Проект по-прежнему проверен одной установкой, моей, а PHP-расширения FreshRSS в нём не работают. Код и инструкции лежат в juev/freshgo, список изменений по версиям на странице релизов7.
freshgo: порт FreshRSS на Go, который перестал быть портом. ↩︎
Issue #210 и замер: условия, все цифры и ограничения. ↩︎
Issue #213 и разбор. ↩︎
Так же поступает Miniflux 2.3.4. Клиент через ClientLogin такой токен и раньше не получал, но сервер его принимал. ↩︎

