🍣

Cloudflare Workersでaws-sdkは利用不可

に公開

Cloudflare Workersでaws-sdkを利用しようとすると、デプロイ後うまく動かない。

これは、aws-sdkがnode.jsの実行環境であるfs関連、確かfs.readを利用するから。
代わりにaws4fetchを使用しましょう。(軽いし、いい)

https://developers.cloudflare.com/r2/examples/aws/aws4fetch/
R2であれば、wangler経由でいいと思いますが。

import { AwsClient } from 'aws4fetch';

export const S3_CONFIG = {
  accessKeyId: process.env.AWS_ACCESS_KEY_ID || '',
  secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY || '',
  region: process.env.S3_REGION || 'us-east-1',
  endpoint: process.env.S3_ENDPOINT || '',
  service: 's3'
} as const;

export const BUCKET_NAME = process.env.S3_BUCKET_NAME || '';

let awsClientInstance: AwsClient | null = null;

export function getAwsClient(): AwsClient {
  if (!awsClientInstance) {
    awsClientInstance = new AwsClient({
      accessKeyId: S3_CONFIG.accessKeyId,
      secretAccessKey: S3_CONFIG.secretAccessKey,
      service: S3_CONFIG.service,
      region: S3_CONFIG.region,
    });
  }
  return awsClientInstance;
}

export function getS3Url(key?: string): string {
  const baseUrl = S3_CONFIG.endpoint;
  if (key) {
    return `${baseUrl}/${BUCKET_NAME}/${key}`;
  }
  return `${baseUrl}/${BUCKET_NAME}`;
}

署名付きURLの生成

async function generatePresignedUrl(filePath: string, expiresIn: number = 3600) {
  const client = getAwsClient();
  const url = getS3Url(filePath);
  
  const signedRequest = await client.sign(
    new Request(`${url}?X-Amz-Expires=${expiresIn}`),
    {
      aws: { signQuery: true }
    }
  );
  
  return signedRequest.url.toString();
}

Discussion