VercelのEdge FunctionでDeepL REST APIを叩こうとした際に、SSL認証エラーが起きました。
- Vercel CLI 37.14.0
- Next.js version: 14.2.15
事象
ローカル環境でvercel dev
した場合は問題なく叩けますが、ステージング環境から叩けない事象が起きました。その他のEdge Functionは動いているので、設定が間違っているとかではなさそう。
app/api/deepl/route.ts
export const dynamic = "force-dynamic";
export const runtime = "edge";
export async function POST(request: Request): Promise<Response> {
...
// URLSearchParamsでリクエストデータを作成
const data = new URLSearchParams((await request.json()).params);
// fetchリクエストの送信
const fetchResponse = await fetch(apiUrl, {
method: "POST",
headers: {
Authorization: `DeepL-Auth-Key ${apiKey}`,
"Content-Type": "application/x-www-form-urlencoded",
},
body: data.toString(),
});
...
}
解決策
ランタイムをNode.jsに変更します。以下の変更だけで問題なく動作しました。
app/api/deepl/route.ts
export const runtime = "nodejs";
原因
原因については色々調べてみましたが、難しかったので諦めました。サーバーレス関数がデプロイされるEdgeでSSL証明書の期限が切れているなどが可能性として考えられますが、その場合こちらからは設定できそうにありません。ご存知の方がいれば教えてください。
補足
fetchでも支障ないですが、Node.js環境であればDeepLのライブラリが使えるので以下のようにします。
app/api/deepl/route.ts
import * as deepl from "deepl-node";
import { isDynamicServerError } from "next/dist/client/components/hooks-server-context";
/**
* DeepL Translate APIのリクエスト型
*/
export type DeepLTranslateAPIRequest = {
text: string;
source_lang: SourceLanguageCode | null;
target_lang: TargetLanguageCode;
};
export const dynamic = "force-dynamic";
export const runtime = "nodejs";
export async function POST(request: Request): Promise<Response> {
try {
const apiKey = process.env.DEEPL_API_KEY;
if (!apiKey) {
throw new Error("DeepL API key is not defined.");
}
const translator = new deepl.Translator(apiKey);
const { text, source_lang, target_lang }: DeepLTranslateAPIRequest = (
await request.json()
).params;
const result = await translator.translateText(
text,
source_lang,
target_lang
);
return new Response(JSON.stringify(result.text), {
headers: { "Content-Type": "application/json" },
});
} catch (error) {
// 動的サーバーエラーは再度スロー
if (isDynamicServerError(error)) {
throw error;
}
// 実行時エラー
return new Response(`Internal Server Error : ${error}`, { status: 500 });
}
}
参考