Skip to content

Fastify 101 Backend Glossary

Published: at 03:22 PM

Table of contents

Open Table of contents

The differences between Decorators, Hooks, Handler Function

Decorator

  • Responsibility: Decorators in Fastify are responsible for extending Fastify’s core objects with additional methods or properties. They allow you to enhance these objects with custom functionality, making it easier to extend Fastify’s capabilities and add reusable features.
  • Scope: Decorators are scoped to Fastify’s core objects such as the Fastify instance (fastify), request object (request), and reply object (reply). You can use decorators to add custom methods or properties to these objects, making them available throughout your application.
  • Usage:
    • Decorators are commonly used to add reusable functionality or utility methods to Fastify’s core objects. For example, you might use decorators to add database access methods to the Fastify instance, request validation helpers to the request object, or response formatting methods to the reply object.
    • Decorators can also be used to encapsulate complex functionality and provide a clean interface for interacting with it. By encapsulating functionality within decorators, you can improve code organization, readability, and maintainability.
// Define a decorator
function customDecorator(fastify, opts, next) {
  // Add a custom method to the Fastify instance
  fastify.decorate("customMethod", function () {
    console.log("Custom method called");
  });

  next();
}

// Register the decorator
fastify.register(customDecorator);

// Now you can use the custom method anywhere in your routes or plugins
fastify.customMethod();

Hooks

  • Responsibility: Hooks allow you to execute code at various points in the request-response lifecycle, providing a way to intercept and modify requests or responses globally or within the scope of a plugin.
  • Scope: Hooks are not tied to individual routes but can be applied globally to all routes or scoped to specific plugins. They execute regardless of the specific route being accessed.
  • Usage: Hooks are used for implementing cross-cutting concerns such as logging, authentication, when a request is received (onRequest), before validation (preValidation), or after sending a response (onSend). or preprocessing of requests or responses.
fastify.addHook("onRequest", async (request, reply) => {
  console.log("Request received");
});

Handler Function

  • Responsibility: For processing the incoming request, performing any necessary operations (such as data retrieval or manipulation), and sending a response back to the client.
  • Scope: They are associated with specific routes and are executed when a request matches the route’s path and method.
  • Usage: Handler functions are defined directly within route definitions and are used to implement the logic for handling specific API endpoints
fastify.get("/users/:id", async (request, reply) => {
  const userId = request.params.id;
  // Retrieve user data from the database
  const user = await User.findById(userId);
  // Send user data back as the response
  reply.send(user);
});

Plugin Function

  • Responsibility: Plugin functions enable you to encapsulate and reuse sets of functionality, including routes, hooks, decorators, and custom utility methods.
  • Scope: Plugins are modular components that can be registered with the Fastify instance to extend its capabilities.
  • Usage: Plugins are typically used to organize and encapsulate related functionality, making it easier to manage and maintain large applications. They can contain route definitions, hooks, and decorators, allowing you to package and reuse complex functionality across different projects or within the same project.

Analogy of each explanation

  1. Decorator:
    • Analogy: Adding seasoning to a dish.
    • Explanation: Just as seasoning enhances the flavor of a dish, decorators enhance the functionality of Fastify’s core objects. They allow you to add extra features or behaviors to these objects without fundamentally changing their structure. For example, you might add a custom method to the Fastify instance or request object using decorators.
// 1. Decorator: Adding seasoning to a dish
// Analogy: Enhancing Fastify's core objects with extra features
// Example: Adding a custom method to the Fastify instance
fastify.decorate("customMethod", function () {
  console.log("Custom method called");
});
  1. Hooks:
    • Analogy: Preparing ingredients before cooking.
    • Explanation: Hooks are like preparation steps you take before cooking. They allow you to perform tasks at specific points in the cooking process, such as marinating meat or chopping vegetables. Similarly, in Fastify, hooks enable you to execute code at various stages of the request-response lifecycle, such as before handling a request or after sending a response.
// 2. Hooks: Preparing ingredients before cooking
// Analogy: Executing code at specific points in the cooking process
// Example: Logging a message before handling each request
fastify.addHook("onRequest", async (request, reply) => {
  console.log("Received a new order");
});
  1. Handler Function:
    • Analogy: Cooking a specific dish.
    • Explanation: Handler functions are like recipes for cooking specific dishes. Each handler function corresponds to a particular route in your application and defines how to handle requests for that route. Just as a recipe specifies the steps for preparing and cooking a dish, a handler function specifies the actions to take when a request matches a particular route, such as fetching data from a database or generating a response.
// 3. Handler Function: Cooking a specific dish
// Analogy: Handling requests for a specific route
// Example: Handling requests to prepare a burger
fastify.get("/prepare-burger", async (request, reply) => {
  // Fetch ingredients, cook patties, assemble burger, etc.
  const burger = {
    type: "Cheeseburger",
    toppings: ["Cheese", "Lettuce", "Tomato", "Onion", "Pickles"],
    isReady: true,
  };
  // Return the prepared burger as the response
  reply.send(burger);
});
  1. Plugin Function:
    • Analogy: Using a specialized kitchen tool or appliance.
    • Explanation: A plugin function is like using a specialized kitchen tool or appliance that helps you perform specific tasks more efficiently. Plugins encapsulate reusable functionality that you can easily integrate into your Fastify application. They can include multiple handler functions, hooks, decorators, or other features packaged together to provide a specific set of capabilities, such as connecting to a database or implementing authentication.
// 4. Plugin Function: Using a specialized kitchen tool or appliance
// Analogy: Integrating reusable functionality into the application
// Example: Using a plugin to manage inventory of ingredients
async function ingredientInventory(fastify, options) {
  // Plugin functionality: Manage inventory of ingredients
  // ...
}

// Wrap the plugin function to make it available to the parent scope
const plugin = require("fastify-plugin");
fastify.register(plugin(ingredientInventory));

In summary, just as seasoning enhances a dish, decorators enhance Fastify’s core objects; hooks are like preparation steps in cooking, allowing you to execute code at specific points in the request-response lifecycle; handler functions are like recipes for handling specific routes; and plugin functions are specialized tools or appliances that encapsulate reusable functionality for your Fastify application.