🔑

Cloudflare R2のファイルに雑にBASIC認証を付ける

2023/10/04に公開

やりたいこと

  • ユーザー名・パスワードを入力しないとダウンロードできないファイルを作りたい
  • 1ファイルに対して複数のユーザー名・パスワードを指定できるようにしたい
    • まだやってないけどKVでユーザー毎にダウンロード数をカウントしたい
  • R2バケット自体のURLは隠したい
  • 細かい事は気にしない

やる

  • Cloudflare WorkersとHonoのBASIC認証ミドルウェア(hono/basic-auth)を使う
  • スマートにやるならKVやD1でユーザー名・パスワードを管理するのがベターだが、面倒くさいので頻繁にデータ更新しないので今回はハードコーディングする

やった

index.ts
type Bindings = {
  BUCKET: R2Bucket;
};

import { Hono } from "hono";
import { basicAuth } from "hono/basic-auth";
import { bridgeFiles } from "../resources";

const app = new Hono<{ Bindings: Bindings }>();

bridgeFiles.forEach((file) => {
  app.use(`/download/${file.endpoint}`, basicAuth(...file.auth));
  app.get(`/download/${file.endpoint}`, async (c) => {
    const object = await c.env.BUCKET.get(file.filename);
    if (object === null) {
      return c.text("Not Found", 404);
    }
    const headers = new Headers();
    object.writeHttpMetadata(headers);
    headers.set("etag", object.httpEtag);
    return new Response(object.body, {
      headers,
    });
  });
});

export default app;

別途resources.tsにユーザー名やパスワード等を記述します。

resources.ts
import { basicAuth } from 'hono/basic-auth';

type Args = Parameters<typeof basicAuth>

export type BridgeFile = {
	filename: string;
	endpoint: string;
	auth: Args;
}

export const bridgeFiles: BridgeFile[] = [
  {
    filename: "test.txt",
    endpoint: "test",
    auth: [
      {
        username: "test",
        password: "test",
      },
      {
        username: "test2",
        password: "test2",
      },
    ],
  },
];

TIPS

  • 今のところR2ファイルの転送時間は課金要件には関係無いので、でかいファイルを置いても問題無い。
  • 実際やってみた所転送速度は3~5MByte/sくらい。速い訳では無いがこの程度なら許容範囲内。

あとがき

Cloudflareさんには頭が上がりませんわほんま

Discussion