📌
Cloud Functions for Firebase + Hono で POST リクエストを受ける
Hono を Cloud Functions for Firebase で動かすにあたり、事前の下調べで @hono/node-server
を使うと POST リクエスト時に500エラーが発生する こと、また、この事象がまだ解決していないことがわかっていたので、@hono/node-server
を使わず以下の記事を参考にアダプタ(handler)を用意しました。
ただ、そのままだとプリフライトリクエストが通らず POST リクエストがコケるため、レスポンスにヘッダーを含めるようにしてこれを回避します。
handler.ts
import { Request as FunctionRequest, Response } from "firebase-functions";
import { Hono } from "hono";
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
export const handler = (app: Hono<any>) => {
return async (req: FunctionRequest, resp: Response) => {
const url = new URL(`${req.protocol}://${req.hostname}${req.url}`);
const headers = new Headers();
// biome-ignore lint/complexity/noForEach: <explanation>
Object.keys(req.headers).forEach((k) => {
headers.set(k, req.headers[k] as string);
});
const body = req.body;
const newRequest = ["GET", "HEAD"].includes(req.method) ?
new Request(url, {
headers,
method: req.method,
}) :
new Request(url, {
headers,
method: req.method,
body: Buffer.from(typeof body === "string" ? body : JSON.stringify(body || {})),
});
const res = await app.fetch(newRequest);
const contentType = res.headers.get("content-type");
// ここから
resp.status(res.status);
resp.set(Object.fromEntries(res.headers));
// ここまで
if (contentType?.includes("application/json")) {
resp.json(await res.json());
} else {
resp.send(await res.text());
}
};
};
プリフライトリクエストではコケたものの、CORS 対応そのものは CORS Middleware のドキュメントそのまま対応する形で完了します。
Discussion