1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

VercelのEdge Functionで525 SSL Handshake Failed

Posted at

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(),
    });
    ...
}

image.png

解決策

ランタイムをNode.jsに変更します。以下の変更だけで問題なく動作しました。

app/api/deepl/route.ts
export const runtime = "nodejs";

image.png

原因

原因については色々調べてみましたが、難しかったので諦めました。サーバーレス関数がデプロイされる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 });
  }
}

参考

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?