Firebase Functions + Realtime Database で何がなんでも CORS エラーが出る

# CORSエラーの解決方法

基本、CORS まわりは下記みたいな感じで解決できるぽい。

```.js
exports.hogehoge = functions.https.onRequest(async (req, res) => {
    res.set("Access-Control-Allow-Origin", "*");
//  res.set("Access-Control-Allow-Origin", "http://localhost:5000"); // URL を書く場合
    res.set("Access-Control-Allow-Headers", "Content-Type"); // これも必要ぽい
    res.set("Access-Control-Allow-Methods", "POST, GET");
    // 何か処理
    res.send({
        data: 'ok'
    }); // res.end() でもよい
```

しかし、「何かの処理」のところで realtime databse にアクセスさせるコードを書くと、そのコードがないときは CORS エラーがでないのに、コードを入れると CORS エラーが出るという謎の状態になってハマりました。

# とりあえず結論

結論から言うと、realtime database にさせる処理でエラーが出ると、なぜか CORS エラーがでることがあるぽい。

# 覚書

書き込むデータの json に undefined が含まれてて、それでエラーになってのを見つけるのに非常に苦労しました。エラーを突き止めるまでに最も苦労したので、手順をかいておきます。

```index.js
const functions = require("firebase-functions");
const admin = require('firebase-admin');

admin.initializeApp();

exports.hogehoge = functions.https.onRequest(async (req, res) => {
    res.set("Access-Control-Allow-Origin", "*");
    res.set("Access-Control-Allow-Headers", "Content-Type");
    res.set("Access-Control-Allow-Methods", "POST, GET");
        res.send({
        data: 'OK'
    }); 

    const json= req.body;
    console.log( json );
    const snapshot = await admin.database().ref('/hoge').push(json);    
});
```

まず、こんなかんじで console.log() で json を出力させるようにしたコードを書いて deploy する。

次に google cloud plattform のコンソールに行ってメニューの中にあるCloud Functions を選ぶ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/75e2a734-2b18-1519-ac71-e9b9eb9ab563.png)


Cloud Functions の画面にいったら deploy した関数名の右のほうにあるメニューから「関数をテスト」を選ぶ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/560a9616-d97b-4c8b-ce33-847374bb998d.png)

すると「コンソール」というタブがあるので、それを押すと `console.log()` で吐いたメッセージを確認できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266247/367ab9d7-f0c8-9c76-8dcd-4f548b86420a.png)

`database().ref().push()` に失敗している旨のエラーが出ていて、これのせいで CORS エラーが出てしまう。なぜ CORS エラーになるのかは分からないのだけど、push が正常にできれば CORS エラーはでない。

これわからんかったわー・・・

ちなみに functions の URL に curl とかブラウザで直接アクセスする場合は、レスポンスを見てるだけでは、エラーになっているのが分からない（つまり、ちゃんとエラーを返すようにすべき）。

途中でエラーになって、ヘッダが表示されてないってことなんだと思うんだけど、これれは分からなかった。

# おまけ

Functions で RealTime Database に書き込むのは、下記のような感じでいけます。

```index.js
const functions = require("firebase-functions");
const admin = require('firebase-admin');

admin.initializeApp();

exports.hogehoge = functions.https.onRequest(async (req, res) => {
    let msg = {
        code: 200,
        message: "success"
    };

    res.set("Access-Control-Allow-Origin", "*");    // テスト時
    // res.set("Access-Control-Allow-Origin", "https://hoge.web.app"); // URL を指定する場合
    res.set("Access-Control-Allow-Headers", "Content-Type");
    res.set("Access-Control-Allow-Methods", "POST, GET");
    
    const body = req.body;
    console.log( body ); // JSON に parse error があると結果的に CROS エラーになる
    const ret = await admin.database()
        .ref('/dat')
        .push(body, (error) => {
            msg = {
                code: 400,
                message: error
            }
        });
    
    res.send( {data: JSON.stringify(msg)} );
    // 何も返さないなら res.end() でも良い
    
});
```