Skip to content

Middlewares

Middleware in GamanJS runs before the route handler and can perform checks, modify context, or stop the request before it reaches the controller.

src/module/middlewares/AppMiddleware.ts
import { composeMiddleware } from 'gaman/compose';
export default composeMiddleware(async (ctx, next) => {
// Logic before handler
console.log(`[${ctx.request.method}] ${ctx.path}`);
// Continue to next handler/middleware
return next();
});

composeMiddleware returns a factory function — it must be called with () when registered.

If middleware needs to stop the request (e.g., auth failure), don’t call next(), return Res directly:

import { composeMiddleware } from 'gaman/compose';
export default composeMiddleware(async (ctx, next) => {
const token = ctx.header('Authorization');
if (!token) {
return Res.message('Unauthorized').unauthorized();
}
// Token valid, continue
return next();
});

Register in defineBootstrap via app.mount():

import { defineBootstrap } from 'gaman';
import router from './router';
import LogMiddleware from './module/middlewares/LogMiddleware';
defineBootstrap(async (app) => {
// Global middleware — runs on ALL routes
app.mount(LogMiddleware());
app.mount(router);
app.mountServer({ http: 3431 });
});

Register directly on route definitions:

import { composeRouter } from 'gaman/compose';
import AuthMiddleware from './module/middlewares/AuthMiddleware';
import UserController from './module/controllers/UserController';
export default composeRouter((r) => {
r.get('/profile', [UserController, 'Profile'])
.middleware(AuthMiddleware());
});

Applied to all routes in the group:

r.group('/admin', (admin) => {
admin.get('/dashboard', [AdminController, 'Dashboard']);
admin.get('/settings', [AdminController, 'Settings']);
}).middleware(AuthMiddleware());

Middleware has a priority that controls execution order. Lower values (higher priority) run first.

import { Priority } from 'gaman/utils';
PriorityValueDescription
MONITOR0Runs first, for logging/monitoring
VERY_HIGH1Very high priority
HIGH2High priority
NORMAL3Default
LOW4Low priority
VERY_LOW5Runs last
export default composeMiddleware(
async (ctx, next) => {
return next();
},
{ priority: Priority.NORMAL }, // default config
);
app.mount(LogMiddleware({ priority: Priority.MONITOR }));
app.mount(AuthMiddleware({ priority: Priority.HIGH }));

Middleware can accept custom configuration:

import { composeMiddleware } from 'gaman/compose';
type CorsConfig = {
origin: string;
methods: string[];
};
export default composeMiddleware<CorsConfig>(
async (ctx, next) => {
ctx.headers.set('Access-Control-Allow-Origin', '*');
return next();
},
{
origin: '*',
methods: ['GET', 'POST'],
priority: Priority.VERY_HIGH,
},
);

Usage:

app.mount(CorsMiddleware({ origin: 'https://example.com' }));

Middleware can store data accessible by handlers:

export default composeMiddleware(async (ctx, next) => {
const user = await verifyToken(ctx.header('Authorization'));
ctx.set('user', user); // Store in context
return next();
});

Access in controller:

GetProfile(ctx) {
const user = ctx.get('user'); // Retrieve from context
return Res.send(user);
}

Middleware pipeline order:

Request → Global Middlewares (sorted by priority) → Route Middlewares → Handler → Response