R2 の一部の 拡張 は、S3 互換 API で使うときに特定のヘッダー設定が必要です。機能によっては、リクエストのカテゴリ全体にリクエストヘッダーを付けたい場合があります。別の場合は、リクエストごとに異なるヘッダーを設定したいこともあります。このページでは、boto3 と aws-sdk-js-v3 での設定例を示します。
cf-create-bucket-if-missing ヘッダーのような機能を使う場合、すべての PutObject リクエストに同じヘッダーを付けたいことがあります。
Boto3 には、リクエストを変更できるイベントシステムがあります。ここでは、すべての PutObject リクエストにヘッダーを追加する関数をイベントシステムへ登録します。
import boto3
client = boto3.resource('s3',
# Provide your Cloudflare account ID
endpoint_url = 'https://<ACCOUNT_ID>.r2.cloudflarestorage.com',
# Retrieve your S3 API credentials for your R2 bucket via API tokens (see: https://developers.cloudflare.com/r2/api/tokens)
aws_access_key_id = '<ACCESS_KEY_ID>',
aws_secret_access_key = '<SECRET_ACCESS_KEY>'
)
event_system = client.meta.events
# Define function responsible for adding the header
def add_custom_header(params, **kwargs):
params["headers"]['cf-create-bucket-if-missing'] = 'true'
event_system.register('before-call.s3.PutObject', add_custom_header)
response = client.put_object(Bucket="my-bucket", Key="my_file", Body="file_contents")
print(response)aws-sdk-js-v3 では、middleware stack ↗ を使ってリクエストの動作をカスタマイズできます。この例では、すべての PutObject リクエストにヘッダーを追加するミドルウェアをクライアントへ追加します。
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
import { HttpRequest } from "@smithy/core/protocols";
const client = new S3Client({
region: "auto", // Required by SDK but not used by R2
endpoint: `https://${ACCOUNT_ID}.r2.cloudflarestorage.com`,
// Retrieve your S3 API credentials for your R2 bucket via API tokens (see: https://developers.cloudflare.com/r2/api/tokens)
credentials: {
accessKeyId: ACCESS_KEY_ID,
secretAccessKey: SECRET_ACCESS_KEY,
},
});
client.middlewareStack.add(
(next) => async (args) => {
const request = args.request;
if (HttpRequest.isInstance(request)) {
request.headers["cf-create-bucket-if-missing"] = "true";
}
return next(args);
},
{ step: "build", name: "customHeaders" },
);
const command = new PutObjectCommand({
Bucket: "my-bucket",
Key: "my_key",
Body: "my_data",
});
const response = await client.send(command);
console.log(response);R2 が S3 互換 API で提供する一部の拡張では、リクエストごとに異なるヘッダーが必要になることがあります。たとえば、etag が期待する値と一致する場合にだけオブジェクトを上書きしたいことがあります。この値は上書き対象のオブジェクトごとに異なるため、リクエストごとに If-Match ヘッダーを変える必要があります。このセクションでは、その方法の例を示します。
client.put_object() の呼び出しに、追加引数としてカスタムヘッダーを渡せるようにするには、boto3 のイベントシステムへ関数を 2 つ登録する必要があります。boto3 はパラメーター検証を行い、余分なメソッド引数を拒否するためです。この検証はリクエストへヘッダーを設定する前に行われるため、先にカスタム引数をリクエストコンテキストへ移します。そのあと、リクエストコンテキストに入れた情報を使って、実際にヘッダーを設定します。
import boto3
client = boto3.resource('s3',
# Provide your Cloudflare account ID
endpoint_url = 'https://<ACCOUNT_ID>.r2.cloudflarestorage.com',
# Retrieve your S3 API credentials for your R2 bucket via API tokens (see: https://developers.cloudflare.com/r2/api/tokens)
aws_access_key_id = '<ACCESS_KEY_ID>',
aws_secret_access_key = '<SECRET_ACCESS_KEY>'
)
event_system = client.meta.events
# Moves the custom headers from the parameters to the request context
def process_custom_arguments(params, context, **kwargs):
if (custom_headers := params.pop("custom_headers", None)):
context["custom_headers"] = custom_headers
# Here we extract the headers from the request context and actually set them
def add_custom_headers(params, context, **kwargs):
if (custom_headers := context.get("custom_headers")):
params["headers"].update(custom_headers)
event_system.register('before-parameter-build.s3.PutObject', process_custom_arguments)
event_system.register('before-call.s3.PutObject', add_custom_headers)
custom_headers = {'If-Match' : '"29d911f495d1ba7cb3a4d7d15e63236a"'}
# Note that boto3 will throw an exception if the precondition failed. Catch this exception if necessary
response = client.put_object(Bucket="my-bucket", Key="my_key", Body="file_contents", custom_headers=custom_headers)
print(response)ここでもミドルウェアを作成して設定したいヘッダーを指定します。ただし今回は、クライアント全体ではなく、リクエスト自体にミドルウェアを追加します。
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
import { HttpRequest } from "@smithy/core/protocols";
const client = new S3Client({
region: "auto", // Required by SDK but not used by R2
// Provide your Cloudflare account ID
endpoint: `https://${ACCOUNT_ID}.r2.cloudflarestorage.com`,
// Retrieve your S3 API credentials for your R2 bucket via API tokens (see: https://developers.cloudflare.com/r2/api/tokens)
credentials: {
accessKeyId: ACCESS_KEY_ID,
secretAccessKey: SECRET_ACCESS_KEY,
},
});
const command = new PutObjectCommand({
Bucket: "my-bucket",
Key: "my_key",
Body: "my_data",
});
const headers = { "If-Match": '"29d911f495d1ba7cb3a4d7d15e63236a"' };
command.middlewareStack.add(
(next) => (args) => {
const request = args.request;
if (HttpRequest.isInstance(request)) {
Object.assign(request.headers, headers);
}
return next(args);
},
{ step: "build", name: "customHeaders" },
);
const response = await client.send(command);
console.log(response);