Skip to content

Instantly share code, notes, and snippets.

@mikesparr
Created October 1, 2025 22:50
Show Gist options
  • Save mikesparr/294e2dbf56d93d482a48ea743c4dbdbd to your computer and use it in GitHub Desktop.
Save mikesparr/294e2dbf56d93d482a48ea743c4dbdbd to your computer and use it in GitHub Desktop.
Example NodeJS Express App Controller Standards Definition

API Controller Standardization Guide

This guide outlines the standards that should be followed to ensure consistency across all controllers in the API.

Controller Structure

Each controller file should follow this structure:

// 1. Imports
const someService = require('../services/someService');
const asyncHandler = require('../utils/asyncHandler');
const { getPaginatedResponse } = require('../utils/pagination');
const { logRequest } = require('../utils/logger');

// 2. Route Handlers
/**
 * Descriptive comment about the endpoint
 * HTTP_METHOD /route/path
 */
const handlerFunction = asyncHandler(async (req, res) => {
  // Extract parameters
  const { param1, param2 } = req.params;
  
  // Log request
  logRequest(req, `Descriptive message about the operation: ${param1}`);
  
  // Call service
  const result = await someService.someMethod(param1, param2, req.body);
  
  // Send response
  res.status(STATUS_CODE).json(result);
});

// 3. Exports
module.exports = {
  handlerFunction1,
  handlerFunction2,
  // ...
};

Error Handling

All route handlers should be wrapped with the asyncHandler utility:

const handlerFunction = asyncHandler(async (req, res) => {
  // Function body
});

The asyncHandler will catch any errors and pass them to the error-handling middleware, eliminating the need for try/catch blocks in each handler.

Request Logging

Every route handler should log the request using the logRequest utility:

logRequest(req, `Descriptive message about the operation: ${param}`);

Pagination

For endpoints that return collections with pagination:

const result = await someService.getItems(params, query);
res.status(200).json(getPaginatedResponse(result, req.query));

HTTP Status Codes

Use consistent HTTP status codes across all endpoints:

  • 200 OK: For successful GET (single resource), PUT, and PATCH requests
  • 201 Created: For successful POST requests that create a new resource
  • 204 No Content: For successful DELETE requests
  • 400 Bad Request: For client errors (invalid input, etc.)
  • 401 Unauthorized: For authentication errors
  • 403 Forbidden: For authorization errors
  • 404 Not Found: For resources that don't exist
  • 409 Conflict: For conflicting operations
  • 500 Internal Server Error: For server errors

Parameter Extraction

Extract parameters at the beginning of the handler function:

const { orgId, envId, resourceId } = req.params;
const { filter, sort } = req.query;
const userId = req.user.id; // From auth middleware

Service Calls

Keep the controller thin by delegating business logic to service files:

const result = await someService.someMethod(parameters);

Response Format

For single resources:

res.status(200).json(resource);

For collections:

res.status(200).json(getPaginatedResponse(result, req.query));

For creation:

res.status(201).json(newResource);

For deletion:

res.status(204).send();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment