Skip to content

Request Pipeline and Middleware

Relevant source files - app.js - config/arcjet.js - controllers/user.controller.js - middlewares/arcjet.middleware.js - middlewares/auth.middleware.js - middlewares/error.middleware.js - models/subscription.model.js - models/user.model.js

This section details the sequential processing of HTTP requests within the Subscription Tracker API. The application utilizes a layered Express.js middleware stack to handle cross-cutting concerns—such as security, parsing, and error handling—before requests reach the domain-specific route handlers.

Request Lifecycle Overview

When a request hits the Express server, it passes through a series of global middlewares defined in app.js before being dispatched to specific routers. The pipeline is designed to fail fast: if a security check (Arcjet) or authentication guard fails, the request is terminated early with an appropriate HTTP status code.

Pipeline Flow Diagram

The following diagram illustrates the path of a request from the client through the middleware stack to the final response or error handler.

Request Flow through app.js

[Flowchart Diagram]

Sources:app.js16-42middlewares/arcjet.middleware.js3-36


Global Middleware Layers

The global stack is initialized in app.js and applies to every incoming request.

1. Pre-Processing and Parsing

The initial layers prepare the request object for downstream consumption:

  • CORS: Configured via cors() to allow cross-origin resource sharing app.js20
  • Body Parsing: express.json() and express.urlencoded() parse incoming request bodies into req.bodyapp.js21-22
  • Cookie Parsing: cookieParser() extracts cookie data into req.cookiesapp.js23
  • Static Files: The public/ directory is served via express.static, providing access to the API tester and Swagger assets app.js24

2. Arcjet Security Layer

The arcjetMiddleware acts as a Web Application Firewall (WAF) and rate limiter. It is placed after the parsers but before the routes to protect the API endpoints.

  • Bypass Logic: To ensure availability, the middleware bypasses checks for health endpoints (/api/v1/health), documentation (/api-docs), and non-API static routes middlewares/arcjet.middleware.js5-10
  • Protection Rules: It utilizes the aj.protect() method with three primary rules defined in config/arcjet.js:

  • Shield: Active WAF protection against common attacks config/arcjet.js9

  • Bot Detection: Blocks malicious bots while allowing search engines config/arcjet.js10-13
  • Token Bucket: Implements rate limiting with a capacity of 10 and a refill rate of 5 tokens every 10 seconds config/arcjet.js14-19
  • Identification: Requests are identified by IP address, extracted from req.ip or the x-forwarded-for header middlewares/arcjet.middleware.js15-18

Sources:app.js25middlewares/arcjet.middleware.js3-36config/arcjet.js4-21


Authentication and Authorization Middleware

While the layers above are global, specific routes (Users, Subscriptions, Test) are protected by the authorize middleware. This middleware bridges the gap between the raw request and the authenticated req.user object.

Logic of middlewares/auth.middleware.js

sequenceDiagram
    participant R as Request
    participant M as authorize Middleware
    participant J as jsonwebtoken
    participant DB as MongoDB (User Model)
    participant C as Controller
    R->>M: Authorization: Bearer <token>
    M->>M: Extract Token
    M->>R: 401 Unauthorized
    M->>J: jwt.verify(token, JWT_SECRET)
    J-->>M: Decoded (userId)
    M->>DB: User.findById(userId).select('-password')
    DB-->>M: userDocument
    M->>R: 401 Unauthorized
    M->>M: req.user = userDocument
    M->>C: next()

Sources:middlewares/auth.middleware.js5-35controllers/user.controller.js17


Global Error Handling

The errorMiddleware is the final layer in the pipeline, attached after all route definitions in app.jsapp.js42 It serves as a centralized catch-all for errors thrown in controllers or previous middlewares.

Specialized Error Handling

The middleware standardizes error responses by detecting specific database and validation errors:

Error Type Detection Criteria Resulting Status
Cast Error err.name === 'CastError' 404 Not Found
Duplicate Key err.code === 11000 400 Bad Request
Validation Error err.name === 'ValidationError' 400 Bad Request
Generic Error Default fallback 500 Internal Server Error

Implementation Detail: For ValidationError, the middleware maps over the Mongoose err.errors object to concatenate all validation messages into a single string middlewares/error.middleware.js21-26

Sources:middlewares/error.middleware.js1-35app.js42