firebase-cloud-functions

Firebase Functions https.onCall()トリガーでアプリから簡単に呼び出す

Firebase Functionsとは、Firebaseの提供するサーバレスフレームワークです。HTTPSリクエストによって関数を実行したり、FireStore・Cloud Storage・AuthenticationのCRUDイベントをトリガーに関数を実行することができます。使用できる言語はJavaScript・TypeScriptに限られているというデメリットはあるものの、手軽にデプロイでき簡単にプロジェクトの他のFirebaseの機能と統合できるメリットがあります。

Firebase Fuctionsとは

Firebase Functions とは、Firebase の提供するサーバーレスフレームワークです。HTTPS リクエストによって関数を実行したり、FireStore・Cloud Storage・Authentication の CRUD イベントをトリガーに関数を実行できます。(残念ながら、無料プランでは利用することはできません・・・)AWS Lambda に近い機能だと言えます。使用できる言語は JavaScript・TypeScript に限られているというデメリットはあるものの、手軽にデプロイでき簡単にプロジェクトの他の Firebase の機能と統合できるメリットがあります。

環境構築

firebase CLIのインストール

Node.js がインストールされていることが前提です。 まずは、firebase CLI をインストールします。

npm install -g firebase-tools

インストールが完了したらバージョンを確認します。

firebase --version
9.1.0

プロジェクトの初期化

まずははじめに、下記コマンドで firebase ツールを認証する必要があります。

firebase login

ブラウザに遷移するのでログインします。

次に、プロジェクトを作成します。コマンドを実行したディレクトリに作成されるので、あらかじめディレクトリをほっておきましょう。

firebase init functions

通常のHTTPリクエスト

HTTP リクエストを処理する場合には、firebase.https を使用します。この関数は、Expressと統合することも可能です。

import { https } from 'firebase-functions'
 
export const hello = https.onRequest((req, res) => {
  res.status(200).json('Hello!')
})

npm run serve コマンドで、ローカル環境で実行できます。 エンドポイントは http://localhost:5001/<project-id>/us-central1/<exoprtした関数名>(hello) です。

アプリから呼び出すときは、通常の REST API 同様 axios などを用いてリクエストを送ることになるでしょう。この例では省略をしていますが実際にはサーバー側でCORSの設定をする必要があるでしょう。

const { data } = axios.get('http://localhost:5001/<project-id>/us-central1/hello`

onCallを利用する

これだけでもサーバーレスとしての機能として申し分ないですが、https.onCall 関数を利用することでさらに簡単に処理を行うことができます。

onCall 関数は次のようになります。

import { https } from 'firebase-functions'
 
export const hello = https.onCall((data, context) => {
  return 'Hello!'
})

onCall 関数は、2 つの引数を受け取ります。data には送信されたパラメータが、context には Firebase Authentication による認証情報が含まれています。

import { https } from 'firebase-functions'
 
export const hello = https.onCall((data, context) => {
  const { id, name } = data
  const { auth, instanceIdToken, rawRequest} = context
 
  auth?.token
  auth?.uid
})

簡単に認証情報が利用できるのが onCall 関数の特徴です。通常認証情報を付与して HTTP リクエストを送信するには、Authentication Header に bearer token といった形で付与して検証するのが一般的ですが、このようなめんどくさい決まりきった処理をすべて行ってくれます。

レスポンスを返すには、JSON エンコード可能なデータを return すれば OK です。

import { https } from 'firebase-functions'
 
export const user = https.onCall(async (data, context) => {
  const user = await User.find(context.auth.uid)
 
  return {
    firstName: user.firstName,
    lastName: user.lastName,
    age: user.age
   }
})

エラーを処理するには、https.HttpsError をスローします。https.HttpsError の第一引数にエラーコードを、第二引数にエラーメッセージを渡します。 第一引数に渡せるエラーコードは以下のとおりです。

FunctionsErrorCode: "ok" | "cancelled" | "unknown" | "invalid-argument" | "deadline-exceeded" | "not-found" | "already-exists" | "permission-denied" | "resource-exhausted" | "failed-precondition" | "aborted" | "out-of-range" | "unimplemented" | "internal" | "unavailable" | "data-loss" | "unauthenticated"

https://firebase.google.com/docs/reference/functions/providers_https_?hl=ja#functionserrorcode

import { https } from 'firebase-functions'
 
export const user = https.onCall(async (data, context) => {
  if (!context.auth) {
    throw new https.HttpsError('unauthenticated', 'auth error')
  }
  const user = await User.find(context.auth.uid)
 
  return {
    firstName: user.firstName,
    lastName: user.lastName,
    age: user.age
   }
})

アプリから呼び出す

onCall で作成した関数をアプリから呼び出してみましょう。

import firebase from 'firebase'
import 'firebase/functions'
 
firebase.initializeApp({
  apiKey: '### FIREBASE API KEY ###',
  authDomain: '### FIREBASE AUTH DOMAIN ###',
  projectId: '### CLOUD FUNCTIONS PROJECT ID ###'
  databaseURL: 'https://### YOUR DATABASE NAME ###.firebaseio.com',
})
 
const functions = firebase.functions()
 
if (process.env.NODE_ENV === 'development') {
  functions.useEmulator('localhost', 5001)
}
const func = functions.httpsCallable('user')
 
const result = func({ id: 'id', name: 'name' })

firebase.functions().httpCallable() で、onCall() で作成した関数を呼び出すことができます。デフォルトの呼び出しですと、デプロイされた Firebase Functions の URL を見に行きますので、ローカル環境で Firebase Functions を利用している際には firebase.functions().useEmulator() でリクエストを送る URL を指定します。

firebase.functions().httpsCallable() の返り値の関数を呼び出すことで、実際にリクエストが送られます。 この引数に渡した値は、onCall の第一引数の data から受け取ることができます。

見てのとおり、認証情報に関する処理は全くありません。Firebase Authentication でログインしていれば自動的に Authentication Header にトークンを付与してくれます。


Contributors

> GitHub で修正を提案する
この記事をシェアする
はてなブックマークに追加

関連記事