Tailwind Logo

Interacting with Next.js API and Playwright's Container (Part 1)

Next.jsRelated Technology

Published: 2023-10-24

We have progressed to the point of running the Playwright container, but this time we will add an API so that it works with the previous Sitecore Search sample site.

Using API

In Next.js, it is possible to operate as an API by placing a file in the path src\pages\api. The hello.ts included in the sample has the following code.

TypeScript
// 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' })
}

When accessing this API, accessing http://localhost:3000/api/hello as the URL will return results as follows.

playwright22.png

Based on the above code, we will build it up.

Sample app

Since getting a screenshot every time is a heavy form of processing, we will create the following as a behavior this time.

  • For the first URL specified
    • Get Screenshot
    • Store that data in Azure Blob Storage
    • Display the data of the image as a result
  • After the 2nd
    • Load data stored in Azure Blob Storage
    • Output read data

In the above case, the URL is used to determine whether the file is to be stored in Azure Blob Storage.

In this case, we will create the following two processes.

  • Get URL
  • Separate the URL into a domain and a filename.

Let's get started with the implementation.

Retrieving URLs

In this case, the thumbnail.ts file will be created using the following code.

TypeScript
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" });
  }
}

You can verify that you are getting it correctly by passing the URL.

playwright23.png

Domain checking and file path generation

The domain name and the file name using the path from the URL will be set. In this case, the path after the domain name is changed to "_" for "/" to determine the file name. Overall, we have rewritten the following.

TypeScript
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" });
  }
}

After obtaining the URL value, it is divided into domain and path, and the result is returned in JSON. For example, the following results are displayed.

playwright24.png

Summary

This time, we have only created the part of the API that obtains a URL and processes it based on the data in that URL. In the next article, we would like to finish the mechanism to return screenshots using the specified URL.

Tags