はじめに
FirebaseのCloud FunctionsでCORSエラーにハマってしまいました。
同じ問題で困っている方のために、原因と解決策をまとめてみます。
やったこと
WebアプリからCloud Functionsのエンドポイントを呼び出そうとした際に、以下のようなCORSエラーが発生しました。
実際のコード
import { onCall } from "firebase-functions/v2/https";
export const getData = onCall(async (request) => {
const data = {
success: true
}
return data
})
CloudFuntion呼び出し部分
```ts
import { httpsCallable } from "firebase/functions";
export class CallFunction {
async callCloudFunction() {
try {
const cloudFunction = getFunctions(app)
const getDataFun = httpsCallable(cloudFunction, 'getData')
const data = await getDataFun()
return data.data;
} catch (error) {
throw error
}
エラーの詳細
ブラウザのdev toolのコンソールで以下のエラーが出ていました。
Access to fetch at 'https://us-central1-app.cloudfunctions.net/getData' from origin 'https://app.web.app' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
ログエクスプローラーのログ
Firebase CloudFunctionのページからGoogle Cloudのログエクスプローラー画面に飛べます。
そこでもログを見てみます。
The request was not authenticated. Either allow unauthenticated invocations or set the proper Authorization header. Read more at https://cloud.google.com/run/docs/securing/authenticating Additional troubleshooting documentation can be found at: https://cloud.google.com/run/docs/troubleshooting#unauthorized-client
対象方法
CORS設定ができていないようです。
Firebase SDKではデフォルトでcorsの設定がされるみたいですが、私の環境ではcorsのエラーが出たままでした。
公式のcorsの説明
Firebase SDKを使用するのを諦めてHTTPで通信する方法を試みます。
解決したコード
以下のように関数を修正することで問題を解決しました:
- onCallからonRequestへの変更:
通常のHTTPリクエストを処理できるように関数タイプを変更しました。 - CORS設定の追加:
レスポンスヘッダーにCORS関連の設定を追加して、クロスオリジンリクエストを許可しました。
実際に修正したコード
export const getData = onRequest(
{
region: 'asia-northeast1'
},
async (req, res) => {
res.set('Access-Control-Allow-Origin', '*');
res.set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
res.set('Access-Control-Allow-Headers', 'Content-Type');
res.status(200).send({
success: true
});
});
呼び出し部分
async getData() {
try {
const res = await fetch(`https://asia-northeast1-app.cloudfunctions.net/getData`)
const data = await res.json();
return data;
} catch (error) {
throw error;
}
}
やったこと
- onRequest関数を使用してHTTPリクエストを直接処理
- Access-Control-Allow-Origin: '*'で全てのオリジンからのアクセスを許可
- Access-Control-Allow-MethodsとAccess-Control-Allow-Headersで必要なメソッドとヘッダーを指定
なお、本番環境ではAccess-Control-Allow-Originを特定のドメインに限定するなど、よりセキュアな設定にすることをお勧めします。
最後に
今回はFirebase SDKの使用を諦めましたが、またリベンジしようと思います。
参考になる公式ドキュメント:
[Firebase Cloud Functionsドキュメント](https://firebase.google.com/docs/functions?hl=ja_
Google Cloud のCORS設定について