Cloudflare R2 の 署名付きURL の取得を Ruby の AWS の gem を用いて実現する

MinIO の場合とほとんど同じです。

obel.hatenablog.jp

事前準備

  • 「R2 API トークンの管理」から、トークン(アクセスキーとシークレットアクセスキー)を予め作成しておきます
  • 「エンドポイント」は https://アカウントID.r2.cloudflarestorage.com/ になるので、これも予め控えておきます

gyazo.com

結論

必要な gem

  • aws-sdk
  • nokogiri
    • nokogiri でなくとも oxogalibxmlrexml でもいいです
    • nokogiri を選んだ理由は、Rails の場合は明示的に入れなくてよく、馴染み深いから、というだけで深い理由はありません

コード

require 'aws-sdk'

s3_client = Aws::S3::Client.new(
  region: 'auto',
  access_key_id: 'YOUR_ACCESS_KEY_ID',
  secret_access_key: 'YOUR_SECRET_ACCESS_KEY',
)

signer = Aws::S3::Presigner.new(client: s3_client)

signed_url = signer.presigned_url(
  :get_object,
  bucket: 'アカウントID.r2.cloudflarestorage.com',
  key: 'bucket_name/path/to/file.jpg',
  expires_in: 60 * 5, # 単位は秒
  virtual_host: true # 大事
)

puts signed_url 

注意する点

注意する点は次のとおりです。

1. region

auto にします。所定の値以外ですと以下のようなエラーになります。

The region name 'ap-northeast-1' is not valid. Must be one of: wnam, enam, weur, eeur, apac, auto

2. bucket

presigned_uri のキーワード引数の bucket に指定する値は「R2 のエンドポイント(スキーム除く)」になります。

3. key

presigned_uri のキーワード引数の key には階層を含めた値を指定しますが、bucket を前述のように指定するため「key の最初の階層が bucket名 に等しく」なります。

4. virtual_host

presigned_uri のキーワード引数の virtual_hosttrue に指定します。これにより、戻り値の signed_url のホスト名に bucket の値が入ってくるようになり、期待通りの戻り値が得られます。

なお、デフォルトの false のままだと戻り値のドメインに AWS のエンドポイントが自動で推測されて入ってきてしまいます*1

docs.aws.amazon.com

docs.aws.amazon.com

余談

MinIO の CLI (mc) で署名付きURLを取得する

MinIO の CLI (mc) を利用する場合は以下のように実行すればいいです。my_r2 という alias が設定済みとします。

$ mc share download --expire 120s my_r2/bucket_name/path/to/file.jpg

AWS の CLI で署名付きURLを取得する

同様のことを AWS の CLI でやりたい場合は次のとおりです。my_cloudflare というプロファイルにクレデンシャルが設定済みとします。

$ aws s3 presign s3://bucket_name/path/to/file.jpg --profile my_cloudflare --endpoint-url https://アカウントID.r2.cloudflarestorage.com --expires-in 120

*1:サブサブドメインが bucket の値で、サブドメイン以降が ap-northeast-1.amazonaws.com のような値が戻り値となる

Powered by はてなブログ