R2 storage from env + filename normalization

This commit is contained in:
2026-08-27 15:41:47 +02:00
parent 9359f26788
commit 0dee178ded
4 changed files with 94 additions and 8 deletions
+62 -7
View File
@@ -52,16 +52,71 @@ masz więcej kolekcji plików: `buildR2Storage(['media', 'documents'])`.
To wzorzec „degrade gracefully" — jak mailAdapter, który wraca do SMTP, gdy brak
Graph. Projekt działa niezależnie od tego, czy R2 jest skonfigurowany.
## Publiczny dostęp (WAŻNE)
## Publiczny dostęp + custom domena (WAŻNE — krok po kroku)
R2 domyślnie prywatny. Upload zadziała, ale obrazy się NIE wyświetlą (403), dopóki
nie skonfigurujesz publicznego odczytu:
R2 domyślnie prywatny. Upload zadziała, ale obrazy się NIE wyświetlą (403),
dopóki nie skonfigurujesz publicznego odczytu przez custom domenę. To proces
w Cloudflare (nie w kodzie), wieloetapowy — poniżej dokładnie.
1. Cloudflare → R2 → bucket → Settings → **Public access** → podłącz custom domain
2. Albo serwuj przez Cloudflare CDN / własną domenę
### Dlaczego custom domena, nie „r2.dev"
Bez tego media wgrają się do R2, ale front nie pokaże obrazów. Konfiguracja domeny
jest po stronie Cloudflare, nie kodu.
R2 oferuje szybki publiczny URL `*.r2.dev`, ALE:
- jest rate-limitowany (nie do produkcji)
- nie przechodzi przez cache Cloudflare (brak CDN, wolniej, drożej)
- brzydki URL (nie Twoja domena)
Dla produkcji ZAWSZE custom domena (np. `media.klient.pl`) — daje CDN, cache,
własny URL. r2.dev tylko do szybkiego testu.
### Warunek wstępny: domena w Cloudflare
Custom domena dla R2 wymaga, żeby domena (albo subdomena) była zarządzana przez
Cloudflare (nameservery klienta wskazują na Cloudflare). Jeśli domena klienta
jest u innego rejestratora — trzeba ją najpierw dodać do Cloudflare (Add Site)
i przełączyć nameservery. Sama subdomena `media.klient.pl` wystarczy, jeśli
główna domena jest już w Cloudflare.
### Krok po kroku — podpięcie custom domeny
1. **Cloudflare Dashboard → R2 → wybierz bucket**
2. Zakładka **Settings** → sekcja **Public access** → **Custom Domains**
3. **Connect Domain** → wpisz subdomenę, np. `media.klient.pl`
4. Cloudflare automatycznie doda rekord CNAME (bo domena jest w Cloudflare) i
wystawi certyfikat SSL. Poczekaj, aż status = **Active** (kilka minut).
5. Od tej chwili pliki są publiczne pod `https://media.klient.pl/<klucz-pliku>`.
### Krok: ustaw publiczny URL w projekcie
Payload musi generować URL-e mediów wskazujące na custom domenę, nie na endpoint
S3. Dodaj zmienną i przekaż ją do adaptera:
```bash
# .env
R2_PUBLIC_URL=https://media.klient.pl
```
Adapter `buildR2Storage` czyta ją i ustawia jako bazowy URL mediów (jeśli
ustawiona). Bez niej Payload zwróci URL wskazujący na prywatny endpoint S3 →
403 na froncie. (Patrz aktualizacja buildR2Storage niżej.)
### Weryfikacja
1. Wgraj obraz w panelu (Media).
2. Sprawdź URL obrazu w panelu — powinien być `https://media.klient.pl/...`,
NIE `https://<account>.r2.cloudflarestorage.com/...`.
3. Otwórz URL w przeglądarce — obraz się pokazuje (nie 403).
4. Na froncie `<img src>` działa.
### Częsty błąd: 403 mimo custom domeny
- **URL wskazuje na endpoint S3, nie custom domenę** → brakuje `R2_PUBLIC_URL`
albo adapter jej nie używa. Sprawdź URL w panelu.
- **Custom domena nie Active** → poczekaj na SSL/CNAME w Cloudflare.
- **Public access wyłączony** → w bucket Settings sprawdź, czy custom domena jest
podpięta (nie tylko utworzona).
Bez tego media wgrają się do R2, ale front pokaże 403. Konfiguracja domeny jest
po stronie Cloudflare, publiczny URL po stronie projektu (.env).
## Migracja istniejących mediów