CloudFunctionでAPIを記述するときの書き方メモです。
onRequest
functions.https.onRequest()
を使うと、一意なURLに対応するAPIを定義することができます。
以下のようなfunctionを定義した場合、https://us-central1-<project-id>.cloudfunctions.net/apiName
というURLでAPIを呼び出すことができます。
exports.apiName = functions.https.onRequest((req, res) => {
// ...
});
また、いくつかAPIを定義する場合Expressの機能を使ってルーティングやmiddlewareの利用をすることができます。
const express = require('express');
const cors = require('cors');
const app = express();
// Automatically allow cross-origin requests
app.use(cors({ origin: true }));
// Add middleware to authenticate requests
app.use(myMiddleware);
// build multiple CRUD interfaces:
app.get('/:id', (req, res) => res.send(Widgets.getById(req.params.id)));
app.post('/', (req, res) => res.send(Widgets.create()));
app.put('/:id', (req, res) => res.send(Widgets.update(req.params.id, req.body)));
app.delete('/:id', (req, res) => res.send(Widgets.delete(req.params.id)));
app.get('/', (req, res) => res.send(Widgets.list()));
// Expose Express API as a single Cloud Function:
exports.widgets = functions.https.onRequest(app);
onCall
onCall
は上述のonRequestをラップしたもので、FirebaseAuthenticationを使った認証やリクエストボディの逆シリアル化などを行なってくれます。
以下のように記述し、data
には逆シリアル化されたデータが含まれ、context
にはユーザーの認証情報が含まれています。
返り値にJson化可能な値を返すことで、APIのレスポンスとすることができます。
exports.addMessage = functions.https.onCall((data, context) => {
// ...
return {
"key": "value"
};
});
/ Message text passed from the client.
const text = data.text;
// Authentication / user information is automatically added to the request.
const uid = context.auth.uid;
const name = context.auth.token.name || null;
const picture = context.auth.token.picture || null;
const email = context.auth.token.email || null;
onRequestで作ったAPIと異なる点は、クライアントサイドでの呼び出しの時に、特定のプロトコルに基づいた呼び出し方をする必要があるというところです。
プロトコル仕様は以下のようになっています。
https://firebase.google.com/docs/functions/callable-reference?hl=ja
SDKが提供されているので、SDKを用いれば楽に呼び出すことができます。
import { getFunctions, httpsCallable } from "firebase/functions";
const functions = getFunctions();
const addMessage = httpsCallable(functions, 'addMessage');
addMessage({ text: messageText })
.then((result) => {
// Read result of the Cloud Function.
/** @type {any} */
const data = result.data;
const sanitizedMessage = data.text;
});