funcnode-s3
funcnode-s3
Клиент S3-совместимого объектного хранилища на Crystal.
Библиотека семейства funcnode: работает с AWS S3, MinIO, Yandex Object Storage и любым другим хранилищем, говорящим на том же протоколе. Только стандартная библиотека — подпись запросов (AWS Signature V4) реализована внутри и закреплена спеками на эталонных примерах из документации AWS.
Возможности
- Объекты —
put_object(байты или поток с известным размером),get_object(в память или в IO),get_object_string,head_object,exists?,delete_object, серверноеcopy_object. - Presigned URL —
presigned_get_url/presigned_put_url/presigned_url: подписанная ссылка действует до истечения срока (до 7 суток), обладателю не нужны ключи доступа, трафик не ходит через приложение. ПинContent-Typeдля загрузок, подписанныеresponse-*-параметры для скачиваний. - Листинг —
each_objectходит по страницам сам;list_objectsотдаёт страницу сcommon_prefixes(«каталоги» через delimiter) и токеном. - Бакеты —
bucket_exists?,create_bucket(сLocationConstraintвне us-east-1),delete_bucket; любой вызов принимаетbucket:. - Надёжность — повторы обрывов сети и 5xx с экспоненциальной задержкой, раздельные таймауты соединения и операции, внятная иерархия ошибок (
ApiErrorс S3-кодом,NotFoundError,TransportError). - Потокобезопасность в многопоточном рантайме Crystal: соединение на запрос, конфиг снимается под локом.
- Path-style и virtual-host адресация; Windows и Linux на равных.
Установка
Добавьте зависимость в shard.yml и выполните shards install:
dependencies:
funcnode-s3:
gitlab: funcnode_crystal/funcnode-s3
Быстрый старт
require "funcnode-s3"
s3 = Funcnode::S3::Client.new("./config/s3.yaml")
s3.put_object("reports/2026-08.pdf", pdf_bytes, content_type: "application/pdf")
data = s3.get_object("reports/2026-08.pdf")
# Ссылка на скачивание для браузера — без ключей на его стороне.
url = s3.presigned_get_url("reports/2026-08.pdf", expires_in: 15.minutes)
Конфигурация
# объектом:
config = Funcnode::S3::Config.new
config.endpoint = "http://127.0.0.1:9000" # локальный MinIO
config.access_key = "minioadmin"
config.secret_key = "minioadmin"
config.bucket = "myapp"
s3 = Funcnode::S3::Client.new(config)
# или путём к YAML-файлу: нет файла — создастся шаблон с дефолтами и
# русскими комментариями, и первый запуск упадёт с ConfigError, чтобы
# оператор его увидел; битый файл — ConfigError тоже:
s3 = Funcnode::S3::Client.new("./config/s3.yaml")
Подробности и YAML-ключи — в руководстве.
Документация
- Руководство — полный API, конфигурация, presigned URL, ошибки, повторы, совместимые хранилища.
- CHANGELOG.md — дельты между релизами; версии — это git-теги (
vX.Y.Z) на веткеmain.
Разработка
crystal spec # многопоточный рантайм — в Crystal >= 1.21 по умолчанию
crystal spec --no-debug # то же с урезанными backtrace
Спеки не требуют внешнего хранилища: сетевые сценарии ходят в локальный стаб-сервер внутри процесса, подпись сверяется с эталонами AWS.
Библиотека предназначена для серверов под Ubuntu 24 — перед релизом обязателен прогон в production-parity контейнере (нужен запущенный Docker):
docker run --rm -v "<путь-к-репо>:/src:ro" crystallang/crystal:1.21.0 bash /src/scripts/linux_spec.sh
Успех — финальная строка LINUX MATRIX GREEN (Ubuntu 24.04, ...).
Участие в разработке
- Сделайте форк (https://gitlab.com/funcnode_crystal/funcnode-s3/-/forks/new)
- Создайте ветку под фичу (
git checkout -b my-new-feature) - Закоммитьте изменения (
git commit -am 'Add some feature') - Запушьте ветку (
git push origin my-new-feature) - Создайте Merge Request
Авторы
- Василий Бутер — автор и мейнтейнер
funcnode-s3
- 0
- 0
- 0
- 0
- 0
- 27 minutes ago
- August 15, 2026
MIT License
Sat, 15 Aug 2026 09:25:34 GMT