【無料枠で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対応と簡易認証付きのプロキシが作れます。

javascript
// 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)を使えば、ターミナルから一発でデプロイできます。

bash
# 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 を渡します。

dart
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なら一瞬でプロキシが立ち上がって便利だと感じました