0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Firebase Local EmulatorでFunctionsのHTTPS呼び出し可能関数を利用するとCORSエラー

Posted at

概要

Firebase Cloud FunctionsのHTTPS呼び出し可能関数をregion指定つけた状態で,FunctionsもエミュレートするようにしたFirebase Local Emulatorからアクセスすると「CORS」エラーが発生してしまいました.本記事はその対処法を記載しています.

解決策まとめ

ブラウザの開発者ツール等からエミュレート実行中のinit.jsの内容をコピーし,Functionsの設定部を下記のように変更し,scriptから利用します.

firebase.app().functions('asia-northeast1').useEmulator(firebaseEmulators.functions.host, firebaseEmulators.functions.port);

環境

  • firebase-tools 9.23.3
  • クライアント側Firebaseソースバージョン 8.8.0 (v8 Web)

発生状況

Firebase Cloud Functionsではクライアント側から認証情報を乗せたまま叩ける「HTTPS呼び出し可能関数」があります.
アプリから関数を呼び出す  |  Firebase Documentation

次のような,EmulatorでFunctionsをテストできるソースがあるとします.

functions/index.js
const functions = require('firebase-functions');
exports.testCall = functions.region('asia-northeast1').https.onCall(async (data, context) => {
  return "ok"
})
public/test.html
<html>
<head>
  <script src="/__/firebase/8.8.0/firebase-app.js"></script>
  <script src="/__/firebase/8.8.0/firebase-auth.js"></script>
</script>
  <script src="/__/firebase/init.js?useEmulator=true"></script>
</head>
(中略)
<script>
const firebaseConfig = { ... }
firebase.initializeApp(firebaseConfig)
const func = firebase.app().functions('asia-northeast1').httpsCallable("testCall")
func()
  .then((r)=>{ console.log(r) })
</script>
</html>

この状態で firebase emulators:start してlocalのtest.htmlにアクセスするとブラウザのコンソールの方に次のようなエラーが出て実行されません.

Access to fetch at 'https://asia-northeast1-xxx.cloudfunctions.net/testCall' from origin 'https://xxx.firebaseapp.com' 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.

init.js?useEmulator=true のscriptタグが無い状態で firebase deploy すると問題なく動くのがやっかいなところです.

原因

実はログにヒントがあり,regionを指定しない場合,つまり

firebase.functions().httpsCallable("testCall")

では

https://localhost:5001/xxxxx/us-central1/testCall

にアクセスするはずですが,ログではデプロイ後のURIにアクセスしています.

同じ現象→ Firebase Functionsを呼び出す際にregion指定するとEmulatorではなく本番に接続してしまう

Emulatorを使うための init.js をブラウザで確認すると,

if (firebaseEmulators.functions && typeof firebase.functions === 'function') {
   firebase.functions().useEmulator(firebaseEmulators.functions.host, firebaseEmulators.functions.port);
}

というコードでFunctionsがエミュレートで動くように設定されていますが, us-central1リージョンのfirebase.functions()だけがエミュレーション動作設定になってしまっており, asia-northeast1リージョンの firebase.app().functions('asia-northeast1')はエミュレート設定になっていないというのが根本原因となります.

対処法

init.js によるエミュレート設定を使う以上は回避できなさそうですので,別途エミュレート設定を記述する必要があります.
init.jsの内容をコピーし,Functionsの設定部を下記のように変更します.

firebase.app().functions('asia-northeast1').useEmulator(firebaseEmulators.functions.host, firebaseEmulators.functions.port);

これにより正常にHTTPS呼び出し可能関数を使うことができるようになりました.

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?