Firebaseによるバックエンドの実装時のCORS設定

記事
IT・テクノロジー

Firebaseによるバックエンドの実装時のCORS設定

Firebaseでバックエンドの実装を行う場合には幾つかの実装方法があります。 同じFirebaseのプロジェクトフォルダでバックエンドもフロントエンドも実装してしまう場合は問題になりませんが、フロントエンドとバックエンドを別々に実装する場合には注意が必要です。
フロントエンドとバックエンドの両方をFirebaseを利用してホスティングする場合でも、開発中に一時的にでもフロントエンドとバックエンドのドメインが同じでない状態になる可能性があります。 そうした場合は最新のWebブラウザの多くがセキュリティ対応の一環で違うドメインへのアクセスをブロックすることがあるからです。
こうした場合は、CORS(Cross Origin Resource Sharing)の設定が必要になります。 例えば、バックエンドのサービスを「https://xxxx-xxxx.web.app」というドメインにすでに公開していて、フロントエンドの開発のテストを「http://localhost:3000」で行ったりする場合です。この二つのサーバのドメインは同じではないので、CORSの設定が正しくされていない場合、最新のWebブラウザがバックエンドのアクセスをブロックしてしまうのでバックエンドのサービスを利用できません。
一方で、フロントエンドとバックエンドをFirebaseの同じプロジェクトフォルダで実装する場合には、この問題は起きません。フロントエンドもバックエンドも同じドメインになるからです。

フロントエンドとバックエンドの両方の実装が必要な場合

開発するWebサービスやWebアプリでフロントエンドとバックエンドの両方で処理が必要な場合にFirebaseを利用してホスティングする場合の作り方は大きく分けて2つの実装方法があります。
* Firebaseのプロジェクトフォルダに両方を実装
* フロントエンドとバックエンドでFirebaseのプロジェクトフォルダを分ける 
どちらも一長一短なので、開発の規模や開発体制によってどちらの方法で実装するかを選ぶ必要があります。シンプルな実装の場合、一緒に実装してしまった方がソースコードの管理やホスティングサーバーの管理も簡単なので便利です。一方で実装が複雑な場合は分けて実装した方が開発時のテストや、サーバーの設定がシンプルになるので便利な場合が多くなります。

Firebaseのプロジェクトフォルダに両方を実装

この方法はつまり、同じドメインに両方のサービスを実装するという事です。当然、フロントエンドとバックエンドは常に同じドメインになるのでCORSの問題は発生しません。
ただし、別の問題があります。フロントエンドにReactやVueのフレームワークを利用する場合で、React RouterやVue Routerのヒストリーモードを使う場合は、フロントエンドとバックエンドの両方でルーティング処理が必要になるので、サーバー側できちんと設定しないとページの切り替えや表示が正しく行えなくなります。
もう一つの問題は、ReactやVueのサポートしている開発用の仕組みが利用できません。どちらも開発用のコンピュータで動作する動作確認用のサーバーを提供しています。この機能を使うと、フロントエンドのコードを変更してファイルを保存すると、変更内容が反映されます。これは、開発時には便利な機能ですが、バックエンドの処理は含まれていないので、バックエンドのサービスが別に必要な場合はこの機能は利用できません。
コードの変更後は、プロダクションイメージを毎回作成して、Firebaseのテスト用のサーバーを起動する必要があります。Firebaseのテスト用のサーバーはバックエンドの機能も同時にホスティングしてくれるので、この方法を使えば開発時のテストは問題ありませんが、少し手間がかかります。

フロントエンドとバックエンドでFirebaseのプロジェクトフォルダを分ける

この方法は、フロントエンドとバックエンドで別々にホスティングを行うという事です。 こうした場合は基本的にCORSの設定が必要になります。
フロントエンドとバックエンドのサーバは基本的に別なので一緒にホスティングする場合よりはサーバー側のルーティングの設定はシンプルです。 また、開発時にも、別々にサーバーを起動する必要があるので、ReactやVueの提供する開発用のサーバー環境も利用可能です。

Firebaseのバックエンドを利用する場合のCORSの設定

CORSの設定のやり方はいろいろありますが、シンプルな方法は、npmのcorsのモジュールを利用してしまうのが簡単です。
npmのcorsのモジュールはミドルウエアと呼ばれるものです。 簡単に言うと、実際の処理を行う際に「間に入って」必要な処理を行ってくれるというものです。中間に入って仕事をしてくれるのでミドルウエアと呼ばれています。
CORSの場合は、フロントエンドとやり取りをする際に、必要な情報(ヘッダーの情報)を自動的に入れてやり取りするようにしてくれます。
利用のやり方は、バックエンドの実装を行うフォルダ、通常は「firebase init」でファンクション(functions)を選択した場合に作られるfunctionsのフォルダに移動してモジュールのインストールを実行します。
$ cd functions
$ npm install cors
$ npm install --save-dev @types/cors
あとは、ミドルウエアの設定をします。expressのバックエンドサーバーのフレームワークを使う場合は以下のような感じで設定します。
import * as express from "express";
const cors = require("cors");
const app:express.Express = express();
app.use(cors());
........
この設定では、全てのドメインからのリクエストを許容するようになります。
特定のドメインや、許容するドメインのリスト(whitelist)を指定することもできます。 詳細は「cors - npm」のドキュメントを見ると書かれています。
CORSの設定は、ドメインだけではなく、使用するHTTPのメソッドによっても制限することが可能で、基本は必要なアクセスのみを許容するように設定します。セキュリティ上必要最小限の設定にするという事です。

実施例は?

例えばシンプルにお問合せフォームのみの実装や登録フォームのみの実装ならば、一つのWebホスティングにしてまとめてしまった方が便利です。
しかし、SendGridのAPIを利用してSendGridとのいろいろなやり取りをバックエンドで実装して、フロントエンド側からSendGridのいろいろな機能を使った、メルマガ(ニュースレター)の実装をする場合は、まとめて実装するよりは、フロントエンドとバックエンドを分けて実装した方が便利です。
別の記事で解説していますが、メルマガ(ニュースレター)のサービスを提供するには、フロントエンドで多くの機能を使う必要が出てきます。
* メッセージの送付先の管理(新規登録、削除、更新、登録者の取得)
* 配布先のリストの管理(リストの新規作成、リストの削除、リストへの登録と削除、リスト一覧の取得)
* 送信者の管理(新規登録、削除、更新、送信者リストの取得)
* メッセージの送信
* メッセージの追跡
など多くの機能が必要です。 この場合はフロントエンドでも複数のページが必要になり、バックエンドでは別々のAPI(URL)が必要になります。このような場合は、サーバー側の設定を含めて、開発の効率化も考えると別々に実装した方が有利です。このような場合は、CORSの設定を行って、別のドメインからのリクエストに対応できるようにするというのが今回の記事で解説している事です。

まとめ

フロントエンドとバックエンドを別々のホスティングで実装する場合は、C最新のWebブラウザは、CORSの設定が正しくされていないと、バックエンドへのアクセスをブロックしてしまうので、予めCORSの設定を行う必要があります。
Firebaseを利用する場合は、npmのモジュールの「cors」のミドルウエアを使うと、簡単に設定が可能です。
サービス数40万件のスキルマーケット、あなたにぴったりのサービスを探す