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 URLpresigned_get_url / presigned_put_url / presigned_url: подписанная ссылка действует до истечения срока (до 7 суток), обладателю не нужны ключи доступа, трафик не ходит через приложение. Пин Content-Type для загрузок, подписанные response-*-параметры для скачиваний.
  • Листингeach_object ходит по страницам сам; list_objects отдаёт страницу с common_prefixes («каталоги» через delimiter) и токеном.
  • Бакетыbucket_exists?, create_bucketLocationConstraint вне 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, ...).

Участие в разработке

  1. Сделайте форк (https://gitlab.com/funcnode_crystal/funcnode-s3/-/forks/new)
  2. Создайте ветку под фичу (git checkout -b my-new-feature)
  3. Закоммитьте изменения (git commit -am 'Add some feature')
  4. Запушьте ветку (git push origin my-new-feature)
  5. Создайте Merge Request

Авторы

  • Василий Бутер — автор и мейнтейнер
Repository

funcnode-s3

Owner
Statistic
  • 0
  • 0
  • 0
  • 0
  • 0
  • 27 minutes ago
  • August 15, 2026
License

MIT License

Links
Synced at

Sat, 15 Aug 2026 09:25:34 GMT

Languages