supabase storageのS3エンドポイントをLaravelで使いたいが困った

Supabase Storageには、S3互換のエンドポイントがついている。
確かに下記のようなライブラリで接続も可能だが、
せっかくS3で接続できるなら、league/flysystem-aws-s3-v3
で済ませたほうがLaravelのデフォルトから離れずに実装できると思った。
→ 4/29追記 結局上記のライブラリに頼ることになった
(今気づいたが、AWSのPHP SDKはJS SDKみたいに分割されておらず、vendorがくっそでかくなる。)
versions
- Laravel 12
-
league/flysystem-aws-s3-v3
: 3.29.0

例えばこうしてみる。driver => s3だが、AWS系の環境変数をsupabaseっぽくリネームしている。
supabaseのプロジェクトが名前空間になるので、AWSと違ってバケットは環境分けしなくていい。ハードコーディングした。
また、サブドメインではなくパスでバケットを指定するよう、use_path_style_endpointをtrueに。
// supabase storageはS3互換なので、s3ドライバーとして設定
// ただし、環境変数がAWS_始まりだと紛らわしいためリネームしている
'supabase' => [
'driver' => 's3',
'key' => env('SUPABASE_S3_ACCESS_KEY'),
'secret' => env('SUPABASE_S3_SECRET_KEY'),
'region' => env('SUPABASE_S3_REGION', 'ap-northeast-1'),
'bucket' => 'storage',
'url' => env('SUPABASE_S3_ENDPOINT'),
'endpoint' => env('SUPABASE_S3_ENDPOINT'),
'use_path_style_endpoint' => true,
'throw' => true,
'report' => false,
],
SUPABASE_S3_ACCESS_KEY=<supabaseローカル立ち上げ時に取得>
SUPABASE_S3_SECRET_KEY=<supabaseローカル立ち上げ時に取得>
SUPABASE_S3_ENDPOINT=http://host.docker.internal:54321/storage/v1/s3
SUPABASE_S3_REGION=local

Storage::disk('supabase')->put('file.txt', 'test')
なにこれ?/file.txtのはずが/v1/s3/storage/file.txtになったんだが...

カスタムS3エンドポイントを league/flysystem-aws-s3-v3
に与えると、このような現象が発生するらしい。ルールベースのエンドポイントを想定しているので、微妙に齟齬があると。
この場合、下記のように EndpointProvider::defaultProvider()
を指定すると、パスが直る。
※configに書くとキャッシュでシリアライズできないためここに書いている
→ 結局この方法でもシリアライズできない
// supabaseのS3に余計なパスがついてしまう現象の対策
// https://github.com/aws/aws-sdk-php/issues/2785
Config::set('filesystems.disks.s3.endpoint_provider', \Aws\Endpoint\PartitionEndpointProvider::defaultProvider());
config:clear後に同じ処理をすると、正常にアップできた。

ただ \Aws\Endpoint\EndpointProvider::defaultProvider()
はdeprecatedになってる。
AWS PHP SDK v3.295.10現在、これ使わずに \Aws\Endpoint\Partition
使えやと書かれてるんだよな。。。かといって\Aws\Endpoint\Partitionの適切な初期化方法が分からない

結局、キャッシュのシリアライズ問題が解決できない。
下記ライブラリで対応した。
S3との違いとして、下記がある
-
エンドポイントに
/storage/v1/s3
をつける必要がない- というか、このライブラリはadmin APIを呼んでいるので、
NEXT_PUBLIC_SUPABASE_URL
に相当するURLを与えればいい
- というか、このライブラリはadmin APIを呼んでいるので、
- アクセスキー・シークレットを発行する必要がない
- keyにはサービスロールキーを指定する