Open6

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

uruositeuruosite

Supabase Storageには、S3互換のエンドポイントがついている。

確かに下記のようなライブラリで接続も可能だが、

https://github.com/quix-labs/laravel-supabase-flysystem

せっかく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
uruositeuruosite

例えばこうしてみる。driver => s3だが、AWS系の環境変数をsupabaseっぽくリネームしている。

supabaseのプロジェクトが名前空間になるので、AWSと違ってバケットは環境分けしなくていい。ハードコーディングした。

また、サブドメインではなくパスでバケットを指定するよう、use_path_style_endpointをtrueに。

config/filesystems.php
        // 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,
        ],
.env
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
uruositeuruosite
Storage::disk('supabase')->put('file.txt', 'test')

なにこれ?/file.txtのはずが/v1/s3/storage/file.txtになったんだが...

uruositeuruosite

カスタムS3エンドポイントを league/flysystem-aws-s3-v3 に与えると、このような現象が発生するらしい。ルールベースのエンドポイントを想定しているので、微妙に齟齬があると。

https://github.com/aws/aws-sdk-php/issues/2785

この場合、下記のように EndpointProvider::defaultProvider() を指定すると、パスが直る。

※configに書くとキャッシュでシリアライズできないためここに書いている

→ 結局この方法でもシリアライズできない

app/Providers/AppServiceProvider.php
        // supabaseのS3に余計なパスがついてしまう現象の対策
        // https://github.com/aws/aws-sdk-php/issues/2785
        Config::set('filesystems.disks.s3.endpoint_provider', \Aws\Endpoint\PartitionEndpointProvider::defaultProvider());

config:clear後に同じ処理をすると、正常にアップできた。

uruositeuruosite

結局、キャッシュのシリアライズ問題が解決できない。
下記ライブラリで対応した。
S3との違いとして、下記がある

  • エンドポイントに /storage/v1/s3 をつける必要がない
    • というか、このライブラリはadmin APIを呼んでいるので、 NEXT_PUBLIC_SUPABASE_URL に相当するURLを与えればいい
  • アクセスキー・シークレットを発行する必要がない
  • keyにはサービスロールキーを指定する

https://github.com/quix-labs/laravel-supabase-flysystem