Keep Your Routes Clean - Use Middleware for Extra Logic

I try to keep my routes as "clean" as i can, additional logic will be executed via middleware - Here's a small example I did with FastAPI

Let's begin with a brief, high-level explanation of middleware. In software development, middleware refers to a helper component that connects different parts of an application. It commonly acts as a mediator between a client and server, facilitating communication and data exchange.

Additionally, middleware can provide various services, including authentication, logging, caching, and more.

middleware

Middleware can simplify many tasks in web development, such as:

  • Handling authentication and authorization
  • Parsing and validating user input
  • Serving static files and compressing responses
  • Logging and error handling
  • Adding security measures to protect against attacks
  • Caching And much more.

In a specific use case, a microservice had a single endpoint for AWS health checks. The aim was to add logging and custom metrics reported to New Relic without cluttering the route method. To achieve this, middleware was utilized instead of embedding the additional functionality in the route method.

Let's take a look:

Route method (HEAD method)

from fastapi import FastAPI

app = FastAPI()


@app.head("/api/v1/health") # This will return 200 in case of successful request
async def health_check():
    return ""

Middleware

from fastapi import Request


@app.middleware("http")
async def response_middleware(request: Request, call_next):
    response = await call_next(request)
    log.info(f"Healthcheck endpoint response: {response.status_code}") # Log the result
    newrelic_custom_event('HealthCheckEndpoint', {'status_code': response.status_code}) # Method that will send a metric with the status code response
    return response

Using middleware instead of adding all the extra logging and New Relic metric in the route method is a better approach because it helps to keep the route method clean and focused on its main purpose of handling HTTP requests and responses. By using middleware, the additional functionality such as logging and metrics can be added to the request/response pipeline in a centralized way, without cluttering the route method with extraneous code. This example might be very minimal but I hope you get the point regardless.

In addition to the above reason, this approach can also improve code maintainability and reusability since the middleware can be reused across multiple routes, rather than having to duplicate the logging and metric code in every route method.



Tags:

Related Articles

Handling CI/CD in a Mono Repo With Multiple Python Packages

Read More

Lab as a Service in DAZN

Read More

Why Makefile is One of My Essentials Tools in Every Software Project

Read More

Easy Minimal CLI Using Appeal Library

Read More