Cross-Origin Resource Sharing(CORS) ↗ は、ドメイン X がドメイン Y のリソースへアクセスするのを防ぐ標準的な仕組みです。ドメイン Y の HTTP レスポンスに特別なヘッダーを付け、ブラウザーが「ドメイン Y はドメイン X からのアクセスを許可している」と確認できるようにします。
CORS は悪意のあるサイトからデータを守る一方で、バケット内のオブジェクト操作や、バケットのポリシー設定にも使います。
ブラウザーからバケットを操作するときは CORS が必要です。次の 2 つの方法があります。
バケットを公開する: バケットをインターネット上で読み取り専用として公開します。誰でもブラウザーやほかの場所からオブジェクトを取得できます。公開ブログで使う画像を置く場合などに向いています。
Presigned URL: 固有の URL を知っている人だけが、バケットに対して指定した操作を実行できます。
CORS を設定する前に、次を用意します。
- オブジェクトを 1 つ以上入れた R2 バケット。バケットがない場合は 公開バケットを作成する を参照してください。
- オブジェクトへアクセスするためのドメイン。
localhostでも構いません。 - (任意)アクセスキー。Presigned URL を作るときだけ必要です。
公開バケットで CORS を使う には、バケットを公開アクセス可能にしておきます。
次に、ファイルを共有できるよう、バケットに CORS ポリシーを追加 します。
Presigned URL を使うと、認証情報を公開せずに、バケットに対する特定の操作を一時的に許可できます。認証は Presigned URL が担いますが、ブラウザーからリクエストする場合は、別途 CORS の設定が必要です。
ブラウザーが別オリジンの Presigned URL へリクエストすると、CORS が適用されます。CORS ポリシーがないと、Presigned URL 自体は有効でも、ブラウザー経由のアップロードとダウンロードは失敗します。
期限切れの Presigned URL は 403 ExpiredRequest を返します。R2 は期限切れの Presigned URL レスポンスに CORS レスポンスヘッダーを付けないため、ブラウザーの JavaScript はエラー本文を読めません。期限切れの前に Presigned URL を更新するか、ブラウザー側で期限切れエラーを直接扱う必要がある場合は、アプリケーションサーバー経由でリクエストします。
Presigned URL でブラウザーからアクセスできるようにする手順は次のとおりです。
-
アプリケーションのオリジンからのリクエストを許可する CORS ポリシーを追加 します。
-
AllowedMethodsには、Presigned URL が実行する操作に合わせてGET、PUT、HEAD、DELETEを指定します。 -
AllowedHeadersには、Presigned URL 利用時にクライアントが送るヘッダー(Content-Type、チェックサム、キャッシュ、カスタムメタデータなど)を含めます。 -
(任意)
ExposeHeadersを設定すると、JavaScript からETagなどのレスポンスヘッダーを読めます。ETagにはオブジェクトのハッシュが含まれ、アップロードの検証に使えます。 -
(任意)
MaxAgeSecondsを設定すると、プリフライトレスポンスをキャッシュし、ブラウザーが送るプリフライトリクエストの回数を減らせます。
次の例は、https://example.com からのブラウザーアップロードを、Content-Type ヘッダー付きで許可します。
[
{
"AllowedOrigins": ["https://example.com"],
"AllowedMethods": ["PUT"],
"AllowedHeaders": ["Content-Type"],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 3600
}
]CORS ポリシーを付けた R2 バケットに カスタムドメイン を接続すると、クロスオリジンリクエスト ↗ に対して CORS レスポンスヘッダーが自動で返されます。
クロスオリジンリクエストには、有効な Origin リクエストヘッダー(例: Origin: https://example.com)が必要です。直接テストしたり curl などのコマンドラインツールを使ったりする場合、リクエストに Origin ヘッダーを付けないと、CORS の Access-Control-* レスポンスヘッダーは見えません。
-
Cloudflare ダッシュボードで R2 object storage ページを開きます。
Overview を開く ↗ -
一覧から対象のバケットを選びます。
-
Settings を選びます。
-
CORS Policy で Add CORS policy を選びます。
-
JSON タブで、ポリシーを手入力するか、コピーしてテキストボックスへ貼り付けます。
-
完了したら Save を選びます。
ポリシーは、そのバケットの Settings ページに表示されます。
Wrangler CLI で CORS ルールを設定できます。
- CORS 設定を書いた JSON ファイルを作成します。
{
"rules": [
{
"allowed": {
"origins": ["https://example.com"],
"methods": ["GET"]
}
}
]
}- CORS ポリシーをバケットに適用します。
npx wrangler r2 bucket cors set <BUCKET_NAME> --file cors.json- CORS ポリシーが適用されたことを確認します。
npx wrangler r2 bucket cors list <BUCKET_NAME>R2 の CORS ポリシーの各フィールドは、HTTP レスポンスヘッダーに対応します。これらのレスポンスヘッダーは、受信した HTTP リクエストが有効な CORS リクエストのときだけ返されます。
| フィールド名 | 説明 | 例 |
|---|---|---|
AllowedOrigins |
ブラウザーからバケット内のオブジェクトをリクエストするとき、R2 が設定する Access-Control-Allow-Origin ヘッダーの値です。 |
www.test.com の Web サイトが、static.example.com の カスタムドメイン 上のリソース(フォント、スクリプトなど)へアクセスする必要がある場合は、AllowedOrigin に https://www.test.com を設定します。 |
AllowedMethods |
ブラウザーからバケット内のオブジェクトをリクエストするとき、R2 が設定する Access-Control-Allow-Methods ヘッダーの値です。 |
GET、POST、PUT |
AllowedHeaders |
ブラウザーからこのバケット内のオブジェクトをリクエストするとき、R2 が設定する Access-Control-Allow-Headers ヘッダーの値です。カスタムヘッダー(x-user-id など)を含むクロスオリジンリクエストでは、これらのヘッダーを AllowedHeaders に指定します。 |
x-requested-by、User-Agent |
ExposeHeaders |
クロスオリジンリクエストを行う JavaScript が、レスポンスから読み取れるヘッダーです。セーフリスト済みのレスポンスヘッダー ↗ 以外(Content-Encoding や cf-cache-status など)へアクセスする場合は、ここに指定します。 |
Content-Encoding、cf-cache-status、Date |
MaxAgeSeconds |
ブラウザーが CORS プリフライトレスポンスをキャッシュしてよい時間(秒)です。最大値(86400)を指定しても、ブラウザーは 2 時間以下に制限することがあります。 | 3600 |
この例は、Roboto-Light.ttf(フォントファイル)を含むバケットに追加した CORS ポリシーです。
AllowedOrigins には利用中の Web サーバーを指定し、localhost:3000 は Web サーバーが動いているホスト名です。AllowedMethods は GET のみを許可し、バケット内のオブジェクトを読み取れます。
[
{
"AllowedOrigins": ["http://localhost:3000"],
"AllowedMethods": ["GET"]
}
]一般に、CORS ルールが正しいかを確認するには、ブラウザーがブロックしているネットワークリクエストを見ます。
- ルールの
AllowedOriginsに、リクエスト元のオリジン(http://localhost:3000やhttps://yourdomain.comなど)が含まれていることを確認します。 - ルールの
AllowedMethodsに、ブロックされたリクエストのメソッドが含まれていることを確認します。 - ルールの
AllowedHeadersに、ブロックされたリクエストのヘッダーが含まれていることを確認します。
また、CORS ルールの反映には、まれに最大 30 秒かかることがあります。
- CORS レスポンスヘッダーが付くのは、クロスオリジンリクエストだけです。
- クロスオリジンリクエストは、
OriginHTTP リクエストヘッダーの有無で識別します。Originの値は、CORS ポリシーのAllowedOriginsで許可された有効なオリジンである必要があります。 OriginHTTP リクエストヘッダーがないリクエストには、CORS レスポンスヘッダーは返りません。Origin の値は完全一致である必要があります。
- クロスオリジンリクエストは、
- CORS ポリシーの
AllowedOriginsの値は、有効な HTTP Origin ヘッダー値 ↗ である必要があります。有効なOriginヘッダーにパスは含めません。scheme://host[:port](ポートは任意)だけです。- 有効な
AllowedOriginsの値:https://static.example.com— スキームとホストを含みます。ポートは任意で、スキームから暗黙に決まります。 - 無効な
AllowedOriginsの値:https://static.example.com/やhttps://static.example.com/fonts/Calibri.woff2— パスが含まれています。
- 有効な
- 動画プレーヤーを使うときなど、オリジンページの JavaScript から特定のヘッダー値を読む必要がある場合は、
Access-Control-Expose-Headersを正しく設定し、Content-Lengthなど JavaScript がアクセスするヘッダーを含めます。