🇬🇧 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 додано до FS3LifecycleRule саме для цього випадку —
перевірено наскрізним тестом проти справжнього бакета 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уFS3LifecycleRuleмають спрацювати, аTagFilters— імовірно ні.
Інший сервіс¶
Оберіть Custom / Other і заповніть поля вручну. Практично завжди потрібно:
- Path Style Addressing — увімкнено. Віртуальні хости серед S3-сумісних сервісів використовує майже виключно Amazon.
- Region — будь-який несуперечливий; якщо сервіс не має регіонів, підійде
us-east-1.
Далі — кнопка Test Connection: якщо конфігурація неправильна, звіт назве конкретне налаштування.
Далі: 9. Тестування