Workers + KV で作る自分だけの短縮URLサービス:入門から実戦まで

なぜ短縮URLサービスを自作するのか?
正直に言うと、私はあるサードパーティの短縮URLサービスを2年近く愛用していました。しかしある朝、全ての短縮リンクが無効になっていることに気づきました——サービスが突然終了したのです。SNSでシェアした数百のリンクが全て404エラーになりました。
その時、「自分だけの短縮URLサービスを作れないか?」と考えました。データが自分の手元にあれば、突然のサービス終了に怯える必要はありませんし、機能も好きにカスタマイズできます。
そこで見つけたのが Cloudflare Workers + KV という組み合わせです。
- 無料枠が凄い:毎日10万リクエストまで無料。
- 爆速:世界200以上のエッジノードで実行されるため、どこからアクセスしても速い。
- 簡単:数行のコードで動き出す。
- データ所有権:データは自分のKVストレージにあるので安心。
この記事では、私が実際に構築した手順をシェアします。カスタム短縮コードの指定や、簡易的なアクセス解析機能も含め、コピペで動くコード付きで解説します。
なぜ Workers + KV なのか?
Cloudflare Workers とは?
簡単に言えば、Cloudflareのエッジネットワーク上で動く「サーバーレス関数」です。コードを書けば、世界中のサーバーに自動でデプロイされ、ユーザーに最も近い場所で実行されます。
太っ腹な無料枠:
- 1日10万リクエスト
- 1リクエストあたり10msのCPU時間
- 個人利用なら十分すぎます。
KVストレージの強み
KV (Key-Value) ストレージは、エッジコンピューティングに最適化されたNoSQLデータベースです。
- 読み込みが超高速:データがエッジにキャッシュされるため、読み込みは爆速(中央値12ms)です。
- 世界規模の同期:書き込みは少し時間がかかりますが(最大60秒)、一度書き込めば世界中で読めます。
- 相性抜群:短縮URLは「短縮コード(Key)」から「元のURL(Value)」を引くだけのシンプルな仕組みなので、KVに最適です。
第三者サービスとの比較
| 特徴 | 一般的な短縮URLサービス | 自作 Workers + KV |
|---|---|---|
| データ所有権 | サービス側に依存 | 完全にご自身のもの |
| カスタマイズ | 制限あり | 自由自在 |
| 持続性 | サービス終了リスクあり | Cloudflareが続く限り安泰 |
| 広告 | 挟まることがある | なし |
| コスト | 有料プランが必要な場合も | ほぼ無料 |
ゼロから作る短縮URLサービス
では、手を動かしていきましょう。
準備作業
1. Cloudflareアカウント作成
cloudflare.com で無料アカウントを作成します。
2. Wrangler CLIのインストール
ローカルで開発するためのツールです。
npm install -g wrangler
# または
yarn global add wranglerインストール後、ログインします:
wrangler login3. プロジェクト作成
mkdir my-shortlink
cd my-shortlink
wrangler initJavaScriptプロジェクトとして作成します。
Step 1: KVネームスペースの作成
データベースの「テーブル」にあたるものを作ります。
# 本番用
wrangler kv:namespace create SHORTLINKS
# プレビュー用(ローカルテストなどで使用)
wrangler kv:namespace create SHORTLINKS --preview実行すると id が表示されるので、これをメモして wrangler.toml に書き込みます。
name = "my-shortlink"
main = "src/index.js"
compatibility_date = "2025-12-01"
# KV設定を追加
[[kv_namespaces]]
binding = "SHORTLINKS"
id = "<あなたの本番用ID>"
preview_id = "<あなたのプレビュー用ID>"binding = "SHORTLINKS" とすることで、コード内で env.SHORTLINKS としてアクセスできるようになります。
Step 2: コードの実装
src/index.js に以下のコードを書きます。
export default {
async fetch(request, env) {
const url = new URL(request.url);
const path = url.pathname.slice(1); // 先頭のスラッシュを削除
// ルートアクセス時
if (path === '') {
return new Response('短縮URLサービスへようこそ!', { status: 200 });
}
// GETリクエスト: リダイレクト処理
if (request.method === 'GET') {
// KVから元のURLを取得
const targetUrl = await env.SHORTLINKS.get(path);
if (targetUrl) {
// 統計情報の更新(非同期で実行し、リダイレクトを遅らせない)
const statsKey = `stats:${path}`;
env.SHORTLINKS.get(statsKey).then(count => {
const newCount = (parseInt(count) || 0) + 1;
env.SHORTLINKS.put(statsKey, newCount.toString());
});
// 301リダイレクト
return Response.redirect(targetUrl, 301);
} else {
return new Response('リンクが見つかりません', { status: 404 });
}
}
// POSTリクエスト: 短縮URL作成
if (request.method === 'POST') {
try {
const body = await request.json();
const { url: targetUrl, code } = body;
if (!targetUrl) {
return new Response('URLが必要です', { status: 400 });
}
// 短縮コードの決定(指定がなければランダム生成)
const shortCode = code || generateRandomCode();
// 重複チェック
const existing = await env.SHORTLINKS.get(shortCode);
if (existing) {
return new Response('そのコードは既に使用されています', { status: 409 });
}
// KVに保存
await env.SHORTLINKS.put(shortCode, targetUrl);
return new Response(JSON.stringify({
shortCode,
shortUrl: `${url.origin}/${shortCode}`,
targetUrl
}), {
status: 201,
headers: { 'Content-Type': 'application/json' }
});
} catch (error) {
return new Response('リクエストエラー', { status: 400 });
}
}
return new Response('Method Not Allowed', { status: 405 });
}
};
// ランダムコード生成関数(6文字)
function generateRandomCode(length = 6) {
const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
let code = '';
for (let i = 0; i < length; i++) {
code += chars.charAt(Math.floor(Math.random() * chars.length));
}
return code;
}Step 3: ローカルテスト
wrangler devサーバーが起動したら(通常 http://localhost:8787)、テストしてみましょう。
短縮URL作成:
curl -X POST http://localhost:8787 \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com"}'レスポンス例:
{
"shortCode": "aBc123",
"shortUrl": "http://localhost:8787/aBc123",
"targetUrl": "https://example.com"
}アクセス確認:
ブラウザで http://localhost:8787/aBc123 にアクセスすると、https://example.com にリダイレクトされるはずです。
Step 4: デプロイ
wrangler deployこれで世界中に公開されました!発行されたURL(例: https://my-shortlink.subdomain.workers.dev)を使ってサービスを開始できます。
Step 5: カスタムドメイン(推奨)
workers.dev ドメインではなく、自分のドメイン(例: link.example.com)を使いたい場合は:
- Cloudflareダッシュボードの「Workers & Pages」へ。
- 作成したWorkerを選択。
- Settings > Triggers > Custom Domains からドメインを追加。
これで、さらにプロフェッショナルな短縮URLサービスの完成です。
発展機能
1. セキュリティ対策
誰でも短縮URLを作れる状態は危険(イタズラやフィッシングに使われる可能性がある)です。簡易的なAPIトークン認証を入れましょう。
// POSTリクエスト処理の先頭に追加
const token = request.headers.get('Authorization');
if (token !== `Bearer ${env.API_TOKEN}`) {
return new Response('Unauthorized', { status: 401 });
}wrangler secret put API_TOKEN でトークンを設定し、クライアント側から送信させます。
2. 有効期限(TTL)の設定
一時的なリンクを作りたい場合、KVの有効期限機能を使えます。
// 24時間 (86400秒) で消える設定
await env.SHORTLINKS.put(shortCode, targetUrl, {
expirationTtl: 86400
});3. アクセス統計API
保存した統計情報を取得するエンドポイントを追加します。
// GETリクエスト処理に追加
if (path.startsWith('stats/')) {
const code = path.replace('stats/', '');
const count = await env.SHORTLINKS.get(`stats:${code}`);
return new Response(JSON.stringify({ code, visits: count || 0 }));
}http://yoursite.com/stats/abc123 にアクセスすると、クリック数が分かります。
まとめ
Cloudflare Workers + KV は、個人開発者がツールを自作するのに最強のプラットフォームです。サーバー管理不要、爆速、そして無料。
今回の短縮URLサービスは、コード量も少なく、初めてのWorkersプロジェクトとしても最適です。ぜひ試してみてください。自分のデータを自分で持つ安心感は、何物にも代えがたいですよ。
Workers + KV 短縮URLサービス構築ガイド
環境構築からデプロイまでのステップバイステップ手順
⏱️ Estimated time: 30 min
- 1
Step1: 環境準備
Cloudflareアカウント作成、Wrangler CLIのインストール、およびログインを完了します。 - 2
Step2: プロジェクトとKV作成
wrangler init でプロジェクトを作成し、wrangler kv:namespace create でKVストレージを確保。IDを設定ファイルに記述します。 - 3
Step3: コーディング
GETリクエストでのリダイレクト処理、POSTリクエストでの短縮URL生成・保存処理を実装します。アクセス統計機能もここに追加可能です。 - 4
Step4: テストとデプロイ
wrangler dev でローカル動作確認を行い、問題なければ wrangler deploy で世界中に公開します。
FAQ
完全に無料ですか?
KVの反映に時間がかかると聞きましたが?
自分のドメインを使えますか?
3 min read · 公開日: 2025年12月1日 · 更新日: 2026年1月22日
関連記事
Next.js ファイルアップロード完全ガイド:S3/Qiniu Cloud 署名付き URL 直接アップロード実践

Next.js ファイルアップロード完全ガイド:S3/Qiniu Cloud 署名付き URL 直接アップロード実践
Next.js Eコマース実践:カートと Stripe 決済の完全実装ガイド

Next.js Eコマース実践:カートと Stripe 決済の完全実装ガイド
Next.js ユニットテスト実践:Jest + React Testing Library 完全設定ガイド


コメント
GitHubアカウントでログインしてコメントできます