【無料枠でOK】Flutterアプリから安全にOpenAI APIを叩くためのCloudflare Workers構築術
はじめに
Flutterで生成AI(OpenAIやAnthropicなど)を使ったスマホアプリを作る際、絶対にやってはいけないのが「アプリ側にAPIキーを直接埋め込むこと」 です。 アプリ内のコードはリバースエンジニアリングで解読されるリスクがあり、APIキーが流出すると高額な請求が来る恐れがあります。
今回は私が開発したスクショ整理アプリ『SnapFolder』で実践した、Cloudflare Workersを使った無料&爆速のAPIプロキシ構築法を紹介します。
アーキテクチャ
仕組みは非常にシンプルです。 Flutterアプリ ⇄ Cloudflare Worker (プロキシ) ⇄ OpenAI API
Worker側にOpenAIのAPIキーを環境変数(シークレット)として持たせ、Flutterからは「アプリ専用の共通シークレットキー」を持たせてWorkerにリクエストを送ります。
1. Cloudflare Workerの実装
まずはCloudflare Workersのコード(JavaScript)です。数行のコードでCORS対応と簡易認証付きのプロキシが作れます。
// worker.js
export default {
async fetch(request, env) {
// CORSプリフライト対応
if (request.method === 'OPTIONS') {
return new Response(null, {
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
},
});
}
if (request.method !== 'POST') {
return new Response('Method not allowed', { status: 405 });
}
// 簡易認証(アプリからの正規リクエストかチェック)
const authHeader = request.headers.get('Authorization');
if (!authHeader || authHeader !== `Bearer ${env.APP_SECRET}`) {
return new Response('Unauthorized', { status: 401 });
}
try {
const body = await request.json();
// OpenAI APIへリクエストを転送
const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${env.OPENAI_API_KEY}`,
},
body: JSON.stringify(body),
});
const data = await response.json();
return new Response(JSON.stringify(data), {
status: response.status,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
},
});
} catch (e) {
return new Response(JSON.stringify({ error: e.message }), { status: 500 });
}
},
}; 2. デプロイとシークレット設定
Wrangler(Cloudflare CLI)を使えば、ターミナルから一発でデプロイできます。
# OpenAIのAPIキーを登録
$ wrangler secret put OPENAI_API_KEY
# アプリ用の独自の認証キー(好きな文字列)を登録
$ wrangler secret put APP_SECRET
# デプロイ!
$ wrangler deploy これで https://your-worker-name.your-subdomain.workers.dev というURLが発行されます。
3. Flutter側からの呼び出し
Flutter側からは、OpenAIのURLの代わりに先ほど発行されたWorkerのURLを叩くだけです。 ヘッダーの Authorization には、Workerに設定した APP_SECRET を渡します。
final response = await http.post(
Uri.parse('https://your-worker-name.your-subdomain.workers.dev'),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $APP_SECRET', // アプリ内共通シークレット
},
body: jsonEncode({
'model': 'gpt-4o-mini',
'messages': [ ... ],
}),
); まとめ
Firebase FunctionsやAWS API Gatewayなどを構築するよりも、Cloudflare Workersなら一瞬でプロキシが立ち上がって便利だと感じました