routing/middleware.md
Middleware
Middleware
Middleware allows application code to run during request processing before the final route handler is executed.
OwnWork uses the middleware facilities provided by Coretex.
Middleware receives the current Request and Response objects together with a continuation callback. It can perform work before continuing, stop the request by returning a result, or continue execution with $next().
Middleware Pipeline
A request with middleware follows this general flow:
Request
│
▼
Global Middleware
│
▼
Route Middleware
│
▼
Route Handler
│
▼
Response OwnWork builds the middleware chain in app/Http/Kernel.php.
The kernel recursively executes each middleware. When a middleware calls $next(), the next middleware in the chain is executed. When there are no more middleware entries, the route resolver executes the route handler.
Conceptually:
Request
│
▼
Middleware A
│
▼
Middleware B
│
▼
Route Handler
│
▼
ResponseMiddleware Signature
The middleware generated by OwnWork uses this signature:
public static function handle(
Request $request,
Response $response,
callable $next
) {
return $next();
}The three arguments represent:
| Argument | Purpose |
|---|---|
$request |
Current HTTP request |
$response |
Current HTTP response |
$next |
Continue to the next middleware or route handler |
The default middleware template generated by the worker defines handle() as a static method.
Creating Middleware
Use the OwnWork worker:
php worker make middleware AuthMiddlewareThe worker creates the file under:
app/Middleware/For example:
app/Middleware/AuthMiddleware.php The generated class uses the App\Middleware namespace and contains a static handle() method.
The worker's component generator creates the file from:
resources/template/Middleware.phpBasic Middleware
A generated middleware can simply continue the request:
<?php
declare(strict_types = 1);
namespace App\Middleware;
use Dhruv125\Coretex\Support\Request;
use Dhruv125\Coretex\Support\Response;
class AuthMiddleware
{
public static function handle(
Request $request,
Response $response,
callable $next
) {
return $next();
}
}Calling:
return $next();passes control to the next middleware.
If there is no next middleware, OwnWork's kernel invokes the route resolver.
Middleware Before the Handler
Code before $next() executes before downstream request processing:
public static function handle(
Request $request,
Response $response,
callable $next
) {
// Runs before downstream processing.
return $next();
}This is useful for request checks, authentication, logging, and other pre-processing operations.
Middleware After the Handler
Code can also run after $next() returns:
public static function handle(
Request $request,
Response $response,
callable $next
) {
$result = $next();
// Runs after downstream processing.
return $result;
}This creates the usual wrapping behavior:
Middleware A
│
├── Before
│
▼
Middleware B
│
├── Before
│
▼
Route Handler
│
└── Return
│
▼
Middleware B
└── After
│
▼
Middleware A
└── After The reverse-order behavior occurs because $next() returns control to the middleware that called it.
Stopping the Pipeline
A middleware does not have to call $next().
It can return a result directly:
public static function handle(
Request $request,
Response $response,
callable $next
) {
if (!$request->has("token")) {
return $response->json([
"message" => "Unauthorized"
]);
}
return $next();
} When the middleware returns without calling $next(), the remaining middleware and route handler are not executed through that path.
Global Middleware
Global middleware applies to requests handled by the application.
Register it through the route object:
$route->globalMiddleware(
[AuthMiddleware::class, "handle"]
);A closure can also be registered:
$route->globalMiddleware(
function ($request, $response, $next) {
return $next();
}
);OwnWork's kernel retrieves the registered global middleware with:
$route->getGlobalMiddleware();It then adds the global middleware to the middleware chain before executing the route-specific middleware.
Global Middleware Parameters
The route API also accepts an optional parameter array when registering global middleware:
$route->globalMiddleware(
[AuthMiddleware::class, "handle"],
[
"role" => "admin"
]
);The parameters are stored as part of the middleware definition.
The middleware implementation is responsible for using any configured parameters.
Route Middleware
Middleware can be associated with an individual route through the router's middleware API:
$route->middleware(
"GET",
"/users",
[AuthMiddleware::class, "handle"]
);The middleware is associated with the specified HTTP method and route URL.
For example, the route itself can be registered as:
$route->get("/users", [
UserController::class,
"index"
]);and middleware can then be attached to that route:
$route->middleware(
"GET",
"/users",
[AuthMiddleware::class, "handle"]
);Applying Middleware to Multiple Routes
The middleware API accepts multiple URLs:
$route->middleware(
"GET",
[
"/users",
"/profile",
"/settings"
],
[AuthMiddleware::class, "handle"]
);The middleware is added to each specified route.
HTTP Method Matters
Route middleware registration includes the HTTP method.
For example:
$route->middleware(
"GET",
"/users",
[AuthMiddleware::class, "handle"]
); A POST route for the same URL is a separate route:
$route->get("/users", [
UserController::class,
"index"
]);
$route->post("/users", [
UserController::class,
"store"
]); Therefore, middleware registered for GET /users should not be assumed to apply automatically to POST /users.
Middleware with Dynamic Routes
Middleware can be associated with a route containing dynamic parameters:
$route->get("/users/{id}", [
UserController::class,
"show"
]);
$route->middleware(
"GET",
"/users/{id}",
[AuthMiddleware::class, "handle"]
);The middleware is associated with the route pattern:
/users/{id}The router resolves the incoming URL and extracts its dynamic parameters before the kernel executes the middleware chain.
Middleware Order
The kernel constructs the final middleware chain from the route middleware and global middleware.
Global middleware is added before the route middleware.
Within the resulting chain, middleware executes in order:
Global Middleware
↓
Route Middleware
↓
Route Handler For middleware that calls $next(), the return path travels in reverse:
Global A before
Route A before
Controller
Route A after
Global A afterThis allows middleware to wrap downstream processing.
Authentication Example
A simple authentication middleware can check request data before allowing the route to continue:
<?php
namespace App\Middleware;
use Dhruv125\Coretex\Support\Request;
use Dhruv125\Coretex\Support\Response;
class AuthMiddleware
{
public static function handle(
Request $request,
Response $response,
callable $next
) {
$token = $request->get("token");
if (!$token) {
return $response->json([
"message" => "Unauthorized"
]);
}
return $next();
}
}The exact authentication mechanism is application-specific. OwnWork's middleware system does not provide an authentication system by itself.
Logging Example
Middleware can also wrap request processing for logging:
<?php
namespace App\Middleware;
use Dhruv125\Coretex\Support\Request;
use Dhruv125\Coretex\Support\Response;
class LoggingMiddleware
{
public static function handle(
Request $request,
Response $response,
callable $next
) {
// Log information about the request.
$result = $next();
// Log information about the completed request.
return $result;
}
}This keeps request-related behavior outside individual controllers.
Middleware and Controllers
Middleware is generally appropriate for behavior that surrounds request execution.
For example:
Middleware
├── Authentication
├── Authorization
├── Logging
└── Request checks
Controller
├── Application operation
├── Service calls
└── View/response creationThe exact division remains an application design decision.
Request Attributes Available to Middleware
Before the middleware chain is executed, OwnWork's kernel sets several request attributes:
$this->request->setAttribute(
'currentRoute',
$result['currentRoute'] ?? '/'
);
$this->request->setAttribute(
'routesArray',
$result['routesArray'] ?? null
);
$this->request->setAttribute(
'dynamicParams',
$dynamicParams
);Therefore middleware can inspect information about the matched route through the request object.
For example:
$currentRoute = $request->getAttribute("currentRoute");
$params = $request->getAttribute("dynamicParams");This happens before OwnWork starts executing the middleware chain.
How OwnWork Executes Middleware
The kernel recursively processes the middleware array.
Conceptually, its execution is:
runMiddlewares()
│
├── Middleware[0]
│ │
│ └── $next()
│ │
│ ▼
├── Middleware[1]
│ │
│ └── $next()
│ │
│ ▼
└── Route ResolverWhen the middleware array is exhausted, the kernel calls the route resolver with the matched handler.
This means middleware does not directly invoke controllers. The final dispatcher passes the matched handler to Coretex's RouteResolver.
Middleware in the Request Lifecycle
Middleware sits after route matching and before route handler resolution.
For example:
GET /users/42
│
▼
Route matching
│
▼
Extract dynamic parameters
│
▼
Set request attributes
│
▼
Global middleware
│
▼
Route middleware
│
▼
RouteResolver
│
▼
Controller / View / Closure
│
▼
Response The OwnWork kernel performs this sequence in app/Http/Kernel.php.
Middleware Checklist
When creating middleware:
- Put application middleware under
app/Middleware/. - Use the generated
App\Middlewarenamespace. - Provide a static
handle()method matching the generated middleware structure. - Accept the request, response, and
$nextcontinuation. - Call
$next()when downstream processing should continue. - Return a result directly when the request should be terminated.
- Register application-wide middleware with
globalMiddleware(). - Register route-specific middleware with
middleware(). - Remember that route middleware registration is associated with an HTTP method and route URL.
- Use request attributes when middleware needs information about the matched route.
application/controllers.md