Playwright のコンテナを動かすところまで進めていきましたが、以前の Sitecore Search のサンプルサイトと連携するように、今回は API を追加します。
コンテンツ更新
ブログで紹介をしていた Playwright のトピックに関しては、最新版では Vercel に展開できるようにしました。以下のページを参照してください。
API の動作に関して
Next.js では src\pages\api のパスにファイルを配置すると、API として動作させることが可能となります。サンプルで入っている hello.ts は以下のようなコードになっています。
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from 'next'
type Data = {
name: string
}
export default function handler(}
req: NextApiRequest,
res: NextApiResponse<Data>
) {
res.status(200).json({ name: 'John Doe' })
}
この API にアクセスする際には、URL として http://localhost:3000/api/hello のようにアクセスすると以下のように結果が返ってきます。
上記のコードをベースに、作りこんでいきます。
作りたいサンプル
毎回スクリーンショットを取得するのは処理が重い形になるため、今回は動作として以下のように作成します。
- 初めて指定された URL に関して
- スクリーンショットを取得
- そのデータを Azure Blob Storage に保存する
- 画像のデータを結果として表示する
- 2回目以降
- Azure Blob Storage に保存されているデータを読み込む
- 読み込んだデータを出力する
上記の場合 URL を利用して Azure Blob Storage にファイルを保存するかどうかを決めて行きます。
今回は以下の2つの処理を作っていきます。
- URL を取得する
- その URL に関してドメインとファイル名に分ける形とする
それではさっそく実装していきます。
URL の取得
今回は thumbnail.ts ファイルを以下のコードを利用して作成をします。
import type { NextApiRequest, NextApiResponse } from "next";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const { url } = req.query as { url: string };
if (!url) {
return res.status(400).json({ error: "Need URL Parameter" });
}
try {
const validUrl = new URL(url);
} catch (error) {
return res.status(400).json({ error: "Invalid URL" });
}
try {
return res.status(200).json({ url: url });
} catch (error) {
return res.status(500).json({ error: "Can't get content data" });
}
}
URL を渡すと正しく取得できていることを確認できます。
ドメインのチェックとファイルパスの生成
URL からドメイン名、およびパスを利用したファイル名を設定してきます。今回は、ドメイン以降のパスのうち / に関しては _ に変更する形でファイル名を決めて行きます。全体的に以下のように書き換えました。
import type { NextApiRequest, NextApiResponse } from "next";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const { url } = req.query as { url: string };
let domain: string | null = null;
let path: string | null = null;
let filename: string | null = null;
// domain check
try {
if (typeof url === "string") {
const parsedUrl = new URL(url);
domain = parsedUrl.hostname;
path = parsedUrl.pathname;
if (!/\..{2,}$/.test(domain)) {
throw new Error("Invalid URL: Domain is not correct");
}
// If the first character is /, remove
path = path.substring(1);
// If path is less than 1 character, rewrite it to index
filename = path.replace(/\./g, "_").replace(/\//g, "_");
// If the last character of filename is _, delete
if (filename.endsWith("_")) {
filename = filename.slice(0, -1);
}
if (filename.length <= 1) {
filename = "index";
}
} else {
throw new Error("Invalid URL");
}
} catch (error) {
console.log(error);
// Returns the response if an error occurs
return { status: 400, body: "Invalid URL" };
}
try {
return res
.status(200)
.json({ domain: domain, path: path, filepath: filename });
} catch (error) {
return res.status(500).json({ error: "Can't get content data" });
}
}
URL の値を取得したあと、ドメインとパスに分けて、その結果を JSON で返している形です。例えば以下のような結果が表示されるようになります。
まとめ
今回は API の動作として URL を取得してその URL のデータを元に処理をする部分のみを作成しました。次回は指定された URL を利用してスクリーンショットを返す仕組みまで仕上げていきたいと思います。