Skip to main content

Route Metadata

RestServer supports attaching metadata to routes, which provides a powerful way to add additional information and behavior to your API endpoints.

Basic Usage

You can attach metadata to routes when defining them:

<?php
use ByJG\RestServer\Route\RouteList;

$routeList = new RouteList();

// Add route with metadata
$routeList->addRoute('GET', '/api/resource', 'MyNamespace\\MyClass::method', null, [
'description' => 'Get a specific resource',
'roles' => ['admin', 'user'],
'cache_ttl' => 3600,
'rate_limit' => 100
]);

Or using the fluent interface with the withMetadata method:

<?php
use ByJG\RestServer\Route\RouteList;

$routeList = new RouteList();
$routeList->addRoute('GET', '/api/resource', 'MyNamespace\\MyClass::method')
->withMetadata([
'description' => 'Get a specific resource',
'roles' => ['admin', 'user']
]);

Accessing Metadata in Controllers

You can access the route metadata in your controller methods:

<?php
namespace MyNamespace;

use ByJG\RestServer\HttpRequest;
use ByJG\RestServer\HttpResponse;

class MyClass
{
public function method(HttpRequest $request, HttpResponse $response)
{
// Get all metadata
$allMetadata = $request->getRouteMetadata();

// Get specific metadata field
$roles = $request->getRouteMetadata('roles');

// Use metadata to customize behavior
if (in_array('admin', $roles)) {
// Include admin-only data
}

$response->write(['result' => 'data']);
}
}

Using Metadata with PHP 8 Attributes

When using PHP 8 attributes for route definitions, you can include metadata:

<?php
namespace MyNamespace;

use ByJG\RestServer\Attributes\RouteDefinition;
use ByJG\RestServer\HttpRequest;
use ByJG\RestServer\HttpResponse;

class MyController
{
#[RouteDefinition('GET', '/api/resource')]
public function getResource(HttpRequest $request, HttpResponse $response)
{
// Method implementation
}
}

// When adding the class to the route list, attach metadata
$routeList = new RouteList();
$routeList->addClass(MyController::class, [
'/api/resource' => [
'GET' => [
'description' => 'Get resource info',
'roles' => ['admin', 'user']
]
]
]);

Predefined Metadata Keys

RestServer uses some predefined metadata keys for special functionality:

KeyDescription
RouteList::META_CLASSThe class or object that handles the route
RouteList::META_METHODThe method to call on the class
RouteList::META_OUTPUT_PROCESSORThe output processor class to use

Common Use Cases

Authentication and Authorization

<?php
// Define routes with authentication requirements
$routeList->addRoute('GET', '/api/public', 'PublicController::getPublicData')
->withMetadata(['requires_auth' => false]);

$routeList->addRoute('GET', '/api/protected', 'ProtectedController::getProtectedData')
->withMetadata(['requires_auth' => true, 'roles' => ['admin']]);

// Create a middleware that checks the authorization requirements
class AuthMiddleware implements BeforeMiddlewareInterface
{
public function beforeProcess($dispatcherStatus, HttpResponse $response, HttpRequest $request): MiddlewareResult
{
$requiresAuth = $request->getRouteMetadata('requires_auth') ?? false;

if ($requiresAuth) {
// Check authentication
if (!$this->isAuthenticated($request)) {
throw new Error401Exception('Authentication required');
}

// Check authorization
$requiredRoles = $request->getRouteMetadata('roles') ?? [];
if (!$this->hasRequiredRoles($request, $requiredRoles)) {
throw new Error403Exception('Insufficient permissions');
}
}

return MiddlewareResult::continue;
}
}

Caching

<?php
// Define routes with caching metadata
$routeList->addRoute('GET', '/api/products', 'ProductController::listProducts')
->withMetadata(['cache_ttl' => 3600]); // Cache for 1 hour

// Create a caching middleware
class CacheMiddleware implements BeforeMiddlewareInterface
{
public function beforeProcess($dispatcherStatus, HttpResponse $response, HttpRequest $request): MiddlewareResult
{
$cacheTtl = $request->getRouteMetadata('cache_ttl');

if ($cacheTtl) {
$cacheKey = $this->generateCacheKey($request);
$cachedResponse = $this->getCachedResponse($cacheKey);

if ($cachedResponse) {
// Return cached response
$response->write($cachedResponse);
return MiddlewareResult::stop;
}
}

return MiddlewareResult::continue;
}
}

Custom Metadata Handlers

You can create custom middleware or components that process specific metadata:

<?php
// Rate limiting middleware using metadata
class RateLimitMiddleware implements BeforeMiddlewareInterface
{
public function beforeProcess($dispatcherStatus, HttpResponse $response, HttpRequest $request): MiddlewareResult
{
$rateLimit = $request->getRouteMetadata('rate_limit');

if ($rateLimit) {
$client = $this->getClientIdentifier($request);
if ($this->hasExceededRateLimit($client, $rateLimit)) {
throw new Error429Exception('Rate limit exceeded');
}
}

return MiddlewareResult::continue;
}
}

By leveraging route metadata, you can add powerful capabilities to your API without cluttering your controller code.