Skip to content

🇬🇧 English | 🇺🇦 Українська

← До змісту

8. Провайдери

Усі перелічені сервіси реалізують той самий API S3, але розходяться в деталях. Обраний провайдер у налаштуваннях закриває більшість із них автоматично; тут — те, що варто знати понад це.

Кожен провайдер у цьому розділі, крім DigitalOcean Spaces, перевірено наскрізним тестом: запис, зчитування, метадані, діапазонний запит, перелік і пакетне видалення — включно з ключами, що містять пробіли, амперсанди й кирилицю. Окремим наскрізним тестом (S3.Live. ResumeInterruptedDownload) перевірено й відновлення перерваного зчитування — те, що If-Match на діапазонному GET дійсно змушує провайдера відмовити застарілій версії об'єкта, а не просто ігнорувати умову. Це не випливає з решти тестів: умовний запит кожен провайдер реалізує самостійно. Ще один окремий тест (S3.Live.CreateAndDeleteBucket) перевіряє створення й видалення бакета, зокрема що видалення непорожнього бакета відхиляється зрозумілою причиною, а не мовчки спорожняє його.

Що працює де

Провайдер Запис і зчитування Багаточастинне + скасування Копіювання Підписані посилання Теги Правила життєвого циклу Відновлення зчитування Створення / видалення бакета
Amazon S3
Cloudflare R2 ❌ 501, не реалізовано
Backblaze B2 ⚠️ баг B2
Google Cloud Storage ❌ 400, не реалізовано ❌ своя схема
MinIO
Wasabi ⚠️ видалення може заблокувати акаунт

✅ перевірено наскрізним тестом проти справжнього сервісу · ⚠️ здебільшого працює, є відома особливість · ❌ провайдер не реалізує цю частину S3 API. Деталі — у розділі кожного провайдера нижче; клікніть назву в таблиці.


Amazon S3

Endpoint URL лишіть порожнім
Region регіон вашого бакета
Path Style Addressing вимкнено

Регіональні адреси. s3.amazonaws.com обслуговує лише us-east-1. Для будь-якого іншого регіону запит має йти на s3.<region>.amazonaws.com, інакше провайдер відповідає 301. Плагін підставляє правильний хост сам — тому поле адреси можна лишити порожнім і просто вказати регіон.

Створення бакета поза us-east-1 вимагає зазначити регіон у тілі запиту. Плагін додає його там, де треба, і не додає там, де це саме по собі було б помилкою.

Імена бакетів глобально унікальні серед усіх клієнтів Amazon. Правдоподібне ім'я зазвичай уже зайняте — це нормально, а не ознака проблеми.


Cloudflare R2

Endpoint URL https://<account-id>.r2.cloudflarestorage.com
Region auto — саме цей літерал
Path Style Addressing увімкнено

Перелік бакетів не працює. R2 не реалізує цю операцію й завжди відповідає 403. Створюйте й переглядайте бакети в панелі Cloudflare.

Теги об'єктів не працюють. R2 відповідає на Set Object Tags кодом 501 NotImplemented — не помилка прав, а пряма відповідь провайдера, що ця частина S3 API в нього відсутня. Якщо теги потрібні саме на R2, використовуйте власні метадані (Set Metadata) — це не той самий механізм (метадані незмінні без перезапису об'єкта), але це те, що R2 підтримує.

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

Правила життєвого циклу вимагають окремого дозволу токена. Get/Set/Delete Bucket Lifecycle — дія рівня бакета, а не рівня об'єкта, і звичайного «Object Read & Write» на R2-токені для неї не досить: без потрібних прав Set Bucket Lifecycle відповідає 403 Access Denied так само, як і будь-яка інша дія без потрібних прав. API сам по собі це підтримує — перевірено наскрізним тестом, і після зміни прав токена спрацювало одразу.

Токен для цього створюється не на загальній сторінці Account → API Tokens (там немає шаблону для R2 узагалі), а саме на сторінці R2 → Manage R2 API Tokens — окремій, з шаблонами рівня самого R2. Там оберіть Admin Read & Write (не просто «Object Read & Write») і, за потреби, звузьте Bucket scope до конкретного бакета.

Стиснення текстових типів. R2 стискає відповіді для текстових Content-Type на льоту. Наслідок, який видно ззовні: для такого об'єкта відповідь несе слабкий ETag (W/"...") і взагалі не містить довжини.

Плагін це враховує: запити метаданих просять нестиснене представлення, а ETag нормалізуються, тож ідентифікатор з R2 порівнюється з ідентифікатором того ж об'єкта в будь-якому іншому сервісі. Спеціально нічого робити не треба — але якщо ви звертаєтеся до R2 повз плагін, про це варто пам'ятати.


Backblaze B2

Endpoint URL https://s3.<region>.backblazeb2.com
Region з поля Endpoint у консолі B2
Path Style Addressing увімкнено

Адреса й регіон залежать від того, де створено бакет. Обидва видно в консолі B2 у властивостях бакета, у полі Endpoint.

Секретний ключ у B2 називається «application key».

Правило життєвого циклу лише з Expire After Days B2 відхиляє. Запит, який на Amazon, MinIO, R2 чи Wasabi приймається без питань, тут повертає 400 MalformedXML з поясненням «є правило Expiration, але немає парного правила ExpiredObjectDeleteMarker з тим самим префіксом» — B2 версійний на нативному рівні, тож Expire After Days там завжди залишає маркер видалення, а не стирає об'єкт одразу. Повне пояснення механізму — у 4. Операції у Blueprint.

Робоча пара правил для B2 — той самий Prefix, різні Id:

Make Array
  [0] Id = "expire-temp"           Prefix = "logs/"    Expire After Days = 30
  [1] Id = "expire-temp-markers"   Prefix = "logs/"    Expire Orphaned Delete Markers = true

Expire Orphaned Delete Markers додано до FDemoS3LifecycleRule саме для цього випадку — перевірено наскрізним тестом проти справжнього бакета B2.

Читання тегів після їх видалення на B2 може повернути 405, а не порожній список. Set Object Tags і перше Get Object Tags після нього працюють нормально; після Delete Object Tags та сама операція Get Object Tags на тому самому об'єкті інколи відповідає 405 MethodNotAllowed замість очікуваного порожнього набору тегів. Поведінка на боці B2, відтворена наскрізним тестом; якщо після видалення тегів на B2 щось раптом падає з 405 там, де раніше працювало, — це воно, а не регресія у вашому коді.

S3 Create Bucket / S3 Delete Bucket потребують ключа з правами на рівні акаунта. Офіційно задокументований сценарій самого B2 — aws s3api create-bucket проти B2-ендпоінта працює так само, як і на будь-якому іншому S3-сумісному провайдері. Але application key, заскоуплений на конкретний бакет (звична практика для B2), прав на створення нового бакета в акаунті не має — провайдер відповість 403 AccessDenied, і плагін покаже саме це, а не мовчазну відмову. Створіть ключ без прив'язки до конкретного бакета, якщо потрібне керування бакетами з коду.


Google Cloud Storage

Endpoint URL лишіть порожнім
Region auto
Path Style Addressing увімкнено

Плагін працює через S3-сумісний XML API Google, а не через рідний API. Тому потрібні HMAC-ключі, а не JSON сервісного облікового запису: у консолі це Cloud Storage → Settings → Interoperability → Create a key.

Google переписує заголовок Accept-Encoding, тож плагін навмисно не включає його в підпис. Це деталь реалізації, але вона пояснює, чому в деяких інших клієнтів запити до GCS повертають 403 там, де до інших сервісів усе працює.

Правила життєвого циклу через S3 API не працюють узагалі. Навіть через «S3-сумісний» XML API в GCS для ?lifecycle — окремий, не-S3 формат тіла запиту: замість стандартних <Filter>/<Status>/<Expiration> там свій словник <Rule><Action>...</Action> <Condition>...</Condition></Rule>. Set Bucket Lifecycle шле коректний документ за специфікацією S3 — той самий, який приймають Amazon, MinIO і (частково) інші провайдери — і GCS відповідає 400 MalformedLifecycleConfiguration, бо це не той документ, якого він чекає. Це не помилка плагіна й не те, що можна виправити кодуванням запиту інакше: щоб керувати життєвим циклом бакета на GCS, задайте правила в консолі Google Cloud Storage.

S3 Create Bucket / S3 Delete Bucket потребують ролі Storage Admin на проєкті. Роль, яку GCS-консоль пропонує за замовчуванням при створенні HMAC-ключа для interoperable-доступу — Storage Object Admin — діє на рівні бакета й не включає право storage.buckets.create, яке офіційно документоване як обов'язкове для створення бакета через XML API; з нею запит повертає 400 InvalidArgument (відтворено і плагіном, і незалежно — тим самим ключем через mc mb, без жодного коду плагіна в шляху). Видайте ключу роль Storage Admin на рівні проєкту замість Storage Object Admin, якщо потрібне керування бакетами з коду.

Створення бакета через XML API додатково вимагає або заголовок x-goog-project-id (плагін його не надсилає — це нестандартне для S3 поле), або заданий у консолі Interoperability проєкт за замовчуванням для сумісного доступу — одноразове налаштування, після якого звичайний запит спрацьовує без додаткового заголовка.


MinIO

Endpoint URL http://host:9000
Region будь-який, але він бере участь у підписі
Path Style Addressing увімкнено

MinIO працює де завгодно — на робочій станції, у вашому дата-центрі, у керованому кластері. Особливості однакові в усіх випадках.

Бакети треба створювати заздалегідь. MinIO не створює бакет на першу спробу запису: ви отримаєте NoSuchBucket. Створіть його нодою S3 Create Bucket, через консоль MinIO або командою mc mb — плагін жодним чином не обмежує спосіб.

Регіон MinIO не перевіряє, але підпис однаково має бути узгодженим, тож поле не можна лишати порожнім. Значення за замовчуванням підходить.

Схема — http://, якщо ви не налаштували TLS. Це найчастіша причина того, що локальний MinIO «не відповідає».


Wasabi

Endpoint URL https://s3.<region>.wasabisys.com, наприклад https://s3.eu-central-1.wasabisys.com
Region той самий, що в адресі — Wasabi не перенаправляє з неправильного регіонального хоста, на відміну від Amazon
Path Style Addressing увімкнено

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

Але видалення бакета акаунт може заблокувати навіть для порожнього бакета. У наскрізному тесті S3 Create Bucket відпрацював нормально, а наступний S3 Delete Bucket на тому самому, щойно створеному й порожньому бакеті відповів 424 Failed Dependency з поясненням «Bucket Delete Activity ... was blocked by Security Contacts in place». Це функція безпеки на рівні акаунта Wasabi (захист від випадкового/зловмисного видалення бакетів, підтверджений контактами безпеки), а не помилка запиту — той самий запит на MinIO, R2 і Amazon S3 відпрацював без питань. Якщо потрібне програмне видалення бакетів на Wasabi, цю функцію доведеться вимкнути або підтвердити в консолі Wasabi заздалегідь; інакше плагін коректно поверне відмову, а не спробує обійти її.


DigitalOcean Spaces

Endpoint URL https://<region>.digitaloceanspaces.com, наприклад https://nyc3.digitaloceanspaces.com
Region той самий, що в адресі
Path Style Addressing увімкнено

⚠️ Не перевірено наживо. На відміну від решти провайдерів цього розділу, DigitalOcean Spaces ще не пройшов наскрізний тест проти справжнього акаунта — усе нижче взято з офіційної документації провайдера, не підтверджено запитом від плагіна. А розходження між заявленим і дійсним тут радше правило, ніж виняток: із шести перевірених наживо провайдерів у трьох (Cloudflare R2, Backblaze B2, Google Cloud Storage) реальна поведінка розійшлася з документацією саме в тегах і правилах життєвого циклу — тобто рівно в тому, що заявлено нижче. Ставтеся до цього як до заявленого, а не доведеного.

За офіційним довідником Spaces API:

  • Теги об'єктів (Get/Put/Delete Object Tags) заявлені як підтримані.
  • Правила життєвого циклу (Get/Set/Delete Bucket Lifecycle) також заявлені як підтримані — але з окремою задокументованою умовою: фільтрувати правило за тегами не можна, лише за префіксом і терміном. Тобто Prefix і ExpireAfterDays у FDemoS3LifecycleRule мають спрацювати, а TagFilters — імовірно ні.

Інший сервіс

Оберіть Custom / Other і заповніть поля вручну. Практично завжди потрібно:

  • Path Style Addressing — увімкнено. Віртуальні хости серед S3-сумісних сервісів використовує майже виключно Amazon.
  • Region — будь-який несуперечливий; якщо сервіс не має регіонів, підійде us-east-1.

Далі — кнопка Test Connection: якщо конфігурація неправильна, звіт назве конкретне налаштування.


Далі: 9. Тестування