Using Middleware with Routes¶
Imagine your application as a factory assembly line. Each product (an HTTP request) must pass through several stations; security checks, quality control, packaging—before it leaves the factory (your controller). In LacePHP those “stations” are called middleware.
Middleware lets you insert reusable, focused logic before (and even after) your controller code runs. This keeps your controllers simple: they only worry about business logic, not every little check or header you need.
Why Middleware Matters¶
Clear Responsibilities: Rather than sprinkling checks and logging throughout your controllers, you group each concern into its own class.
Consistency: Every route that needs CORS headers or authentication gets the same logic, so nothing slips through the cracks.
Reusability: Write a middleware once and attach it to many routes or route-groups—no copy-and-paste.
Flexibility: Turn middleware on or off via configuration (in lace.json), or apply it only to specific routes.
Built-In Middleware You Can Use¶
LacePHP already includes several ready-made middleware. Here’s a quick reference:
Middleware |
Class |
Description |
---|---|---|
CORS |
|
Adds the headers browsers need for cross-origin requests and handles OPTIONS preflight automatically. |
Debug Logging |
|
When you append |
Rate Limiting |
|
Limits how many requests a single IP can make in a time window (default 60 requests per 60 seconds). |
Response Caching |
|
Stores GET responses on disk and serves them directly when caching is enabled, speeding up repeat requests. |
Each of these lives under the PHP namespace LaceboxKnots. You do not need to write them yourself, just attach them to your routes.
Attaching Middleware to a Single Route¶
To protect or enhance one specific endpoint, you can attach middleware in your route definition. For example, to combine CORS and rate-limiting on a /api/data route:
use Lacebox\Knots\CorsKnots;
use Lacebox\Knots\RateLimitKnots;
use Weave\Middlewares\ExampleMiddleware;
use Weave\Controllers\DataController;
$router->addRoute(
'GET', # HTTP method
'/api/data', # path
[DataController::class, 'index'],[ # controller + method
CorsKnots::class, # new CorsKnots()
[RateLimitKnots::class, [100, 60]], # new RateLimitKnots(100, 60)
ExampleMiddleware::class # your own custom middleware
]
);
Step-by-step what happens:
CORS headers are sent (so browsers can call this API from other domains).
Rate limit of 100 requests per 60 seconds is enforced—extra requests return HTTP 429.
ExampleMiddleware runs (perhaps checking an API key or logging).
Finally, DataController::index() is called to handle the request.
Grouping Multiple Routes¶
Often many routes share the same requirements. Instead of repeating the middleware list, you group them:
use Lacebox\Knots\MagicDebugKnots;
use Lacebox\Knots\ShoeCacheKnots;
$router->group(
[ # group options
'prefix' => '/reports', # all routes start with /reports
],
function($r) {
$r->sewGet('/sales', ['ReportController', 'sales']);
$r->sewPost('/inventory',['ReportController', 'inventory']);
}
)->middleware([
MagicDebugKnots::class, # log debug info if ?debug=lace
ShoeCacheKnots::class, # cache GET responses
]);
Here both /reports/sales and /reports/inventory:
Log start/end markers when ?debug=lace is present
Serve cached JSON if available
You can still attach extra middleware to individual routes inside the group:
$router->group(
['prefix' => '/admin',
'namespace' => 'Controllers\Admin'],
function($r) {
$r->get('/dashboard', ['AdminController', 'index']);
$r->post(
'/users',
['UserController', 'store'],
['SomeOtherMiddleware::class'] # only for /admin/users
);
}
);
In this example:
The group middleware (perhaps authentication) applies to every /admin/* route.
`SomeOtherMiddleware` runs only for the /admin/users POST request, letting you layer extra checks or features on top.
Best Practice Checklist¶
Give each middleware one clear job (e.g. AuthKnots, ThrottleKnots, CorsKnots).
Order matters: place security checks first, rate-limits next, then logging or caching.
Use constructor arguments when your middleware needs settings (e.g. new RateLimitKnots(50,30)).
Keep middleware lightweight—delegate heavy work to services or your controllers.
Common Pitfalls & Cautions¶
Warning
Remember to stop the request if you block it: echo or return a response and call exit.
Avoid raw calls to header() or echo after middleware chaining; use kickback() to manage HTTPS response codes and headers.
Check the HTTP method inside your middleware when you only want it to run on GET or POST.
By organising cross-cutting logic into middleware and attaching it clearly to your routes, you ensure your LacePHP app is both secure and maintainable—exactly what a junior developer needs to build confidence and clarity.