November 12, 2024

Implementing Custom Middleware in SvelteKit

If you’re looking to extend the functionality of your SvelteKit application, implementing custom middleware is a powerful technique. Middleware allows you to execute code before the request is processed, providing a flexible way to enhance features like authentication, logging, and data fetching.

What is Middleware in SvelteKit?

Middleware in SvelteKit is a function that has access to the request, response, and next middleware in the application’s request-response cycle. By utilizing middleware, you can manipulate the incoming request, add custom logic, or even short-circuit processing based on certain conditions.

Setting Up a SvelteKit Project

First, ensure you’ve set up your SvelteKit project. If you’re starting from scratch, run the following command:

bunx sv create app

Navigate into your project directory:

cd app

Creating Custom Middleware

To create a custom middleware, you can define a new file in the src/middleware directory. Here’s how you can set up a simple logging middleware that logs the request method and URL.

  1. Create the Middleware File

Create a file named logger.ts in the src/middleware directory:

import type { RequestHandler } from "@sveltejs/kit";

export const logger: RequestHandler = async ({ request, resolve }) => {
  console.log(`Request Method: ${request.method}, URL: ${request.url}`);

  const response = await resolve(request);
  return response;
};
  1. Register the Middleware

Next, you need to register the middleware in your application. Open the src/hooks.server.ts file and import your middleware:

import { logger } from "./middleware/logger";

export const handle = logger;

This configuration allows the logger middleware to process every incoming request.

Implementing Middleware with Authentication Logic

Let’s take it a step further and implement an authentication middleware. This example checks if a user is authenticated based on a cookie value.

  1. Create Auth Middleware

Create a file named auth.ts in the src/middleware directory:

import type { RequestHandler } from "@sveltejs/kit";
import { redirect } from "@sveltejs/kit";

export const auth: RequestHandler = async ({ request, resolve }) => {
  const session = request.headers.get("cookie")?.includes("session_id");

  if (!session) {
    throw redirect(302, "/login");
  }

  const response = await resolve(request);
  return response;
};
  1. Register the Auth Middleware

Again, open the src/hooks.server.ts file and register the auth middleware:

import { logger } from "./middleware/logger";
import { auth } from "./middleware/auth";

export const handle = logger(auth);

With this setup, any request without a valid session will redirect users to the login page.

Handling Errors Globally

You can also implement middleware for global error handling. For instance, you can create an error middleware that captures any unhandled errors and formats them into a user-friendly message.

  1. Create Error Handling Middleware

Create a file named errorHandler.ts in the src/middleware directory:

import type { RequestHandler } from "@sveltejs/kit";

export const errorHandler: RequestHandler = async ({ request, resolve }) => {
  try {
    const response = await resolve(request);
    if (response.status >= 400) {
      // Handle the error response accordingly
      console.error(`Error response: ${response.status}`);
    }
    return response;
  } catch (error) {
    console.error(`Caught error: ${error}`);
    return new Response("Internal Server Error", { status: 500 });
  }
};
  1. Register the Error Handler

Finally, update your src/hooks.server.ts file to include the error handler:

import { logger } from "./middleware/logger";
import { auth } from "./middleware/auth";
import { errorHandler } from "./middleware/errorHandler";

export const handle = logger(auth(errorHandler));

Conclusion

Implementing custom middleware in your SvelteKit application can significantly enhance its functionality and maintainability. Whether you need logging, authentication, or error handling, middleware offers a straightforward way to manage and customize the request lifecycle.

By following the examples above and adapting them to your needs, you can create a robust architecture for your SvelteKit app. Happy coding!