Router API Reference
The Router class manages event routing for both WebSocket events and HTTP requests in Sockeon. It handles attribute-based routing and middleware execution.
Class: Sockeon\Sockeon\Core\Router
Constructor
public function __construct(Server $server)
Creates a new Router instance.
Parameters:$server
(Server
): The server instance
Controller Registration
register()
public function register(SocketController $controller): void
Registers a controller and scans it for route attributes.
Parameters:$controller
(SocketController
): The controller instance to register
$router = new Router($server);
$router->register(new ChatController());
$router->register(new GameController());
- Sets the server instance on the controller
- Uses reflection to scan all public methods
- Registers methods with routing attributes (
#[SocketOn]
,#[HttpRoute]
,#[OnConnect]
,#[OnDisconnect]
) - Stores middleware configuration for each route
WebSocket Event Routing
dispatch()
public function dispatch(int $clientId, string $event, array $data): void
Routes a WebSocket event to the appropriate handler method.
Parameters:$clientId
(int
): The client ID that sent the event$event
(string
): The event name$data
(array<string, mixed>
): The event data
// This is called internally by the server
$router->dispatch(123, 'chat.message', [
'message' => 'Hello world!'
]);
- Checks if a handler exists for the event
- Executes event-specific middleware
- Calls the handler method with client ID and data
- Handles any exceptions and sends error responses
HTTP Request Routing
dispatchHttp()
public function dispatchHttp(Request $request): mixed
Routes an HTTP request to the appropriate handler method.
Parameters:$request
(Request
): The request object
mixed
- The HTTP response
Example:
// This is called internally by the server
$response = $router->dispatchHttp($request);
- Matches the method and path against registered routes
- Extracts path parameters (e.g.,
{id}
from/users/{id}
) - Executes HTTP-specific middleware
- Calls the handler method with the request
- Returns the response or a 404 if no route matches
Connection Event Routing
routeConnect()
public function routeConnect(int $clientId): void
Routes client connection events to registered connect handlers.
Parameters:$clientId
(int
): The newly connected client ID
// Called when a client connects
$router->routeConnect(123);
routeDisconnect()
public function routeDisconnect(int $clientId): void
Routes client disconnection events to registered disconnect handlers.
Parameters:$clientId
(int
): The disconnected client ID
// Called when a client disconnects
$router->routeDisconnect(123);
Middleware Management
addGlobalMiddleware()
public function addGlobalMiddleware(string $middlewareClass): void
Adds a middleware class that will be executed for all routes.
Parameters:$middlewareClass
(string
): The fully qualified middleware class name
$router->addGlobalMiddleware(AuthenticationMiddleware::class);
$router->addGlobalMiddleware(LoggingMiddleware::class);
setGlobalMiddlewares()
public function setGlobalMiddlewares(array $middlewares): void
Sets the complete list of global middleware classes.
Parameters:$middlewares
(array<string>
): Array of middleware class names
$router->setGlobalMiddlewares([
AuthenticationMiddleware::class,
LoggingMiddleware::class
// Note: Rate limiting is handled automatically via #[RateLimit] attribute
]);
Route Information
getWebSocketRoutes()
public function getWebSocketRoutes(): array
Returns all registered WebSocket event routes.
Returns:array<string, array>
- Associative array of event names to route info
Example:
$routes = $router->getWebSocketRoutes();
/*
Returns:
[
'chat.message' => [
'controller' => ChatController::class,
'method' => 'handleMessage',
'middlewares' => [],
'excludeGlobalMiddlewares' => []
],
'user.login' => [
'controller' => AuthController::class,
'method' => 'handleLogin',
'middlewares' => [],
'excludeGlobalMiddlewares' => [AuthMiddleware::class]
]
]
*/
getHttpRoutes()
public function getHttpRoutes(): array
Returns all registered HTTP routes.
Returns:array<string, array>
- Associative array of route patterns to route info
Example:
$routes = $router->getHttpRoutes();
/*
Returns:
[
'GET /api/users' => [
'pattern' => '/api/users',
'method' => 'GET',
'controller' => UserController::class,
'handler' => 'listUsers',
'middlewares' => [AuthMiddleware::class],
'excludeGlobalMiddlewares' => []
],
'POST /api/users' => [
'pattern' => '/api/users',
'method' => 'POST',
'controller' => UserController::class,
'handler' => 'createUser',
'middlewares' => [AuthMiddleware::class, ValidationMiddleware::class],
'excludeGlobalMiddlewares' => []
]
]
*/
getConnectHandlers()
public function getConnectHandlers(): array
Returns all registered connection handlers.
Returns:array<array>
- Array of connect handler info
Example:
$handlers = $router->getConnectHandlers();
/*
Returns:
[
[
'controller' => ChatController::class,
'method' => 'onConnect',
'middlewares' => [],
'excludeGlobalMiddlewares' => []
]
]
*/
getDisconnectHandlers()
public function getDisconnectHandlers(): array
Returns all registered disconnection handlers.
Returns:array<array>
- Array of disconnect handler info
Path Parameter Extraction
The router automatically extracts path parameters from HTTP routes and adds them to the request.
Parameter Syntax
Use curly braces to define parameters in route paths:
#[HttpRoute('GET', '/api/users/{id}')]
public function getUser(Request $request): Response
{
$userId = $request->getParam('id');
return Response::json(['user' => ['id' => $userId]]);
}
#[HttpRoute('GET', '/api/users/{userId}/posts/{postId}')]
public function getUserPost(Request $request): Response
{
$userId = $request->getParam('userId');
$postId = $request->getParam('postId');
return Response::json([
'user' => $userId,
'post' => $postId
]);
}
Matching Process
- Route patterns are converted to regular expressions
- Parameters are captured as named groups
- Captured values are added to the request object
- Parameters are available via
$request->getParam()
Middleware Execution
WebSocket Middleware
Middleware for WebSocket events is executed in this order:
- Global middleware (unless excluded)
- Route-specific middleware (from
#[SocketOn]
attribute)
class ChatController extends SocketController
{
#[SocketOn('private.message', middlewares: [AuthMiddleware::class, PrivacyMiddleware::class])]
public function handlePrivateMessage(int $clientId, array $data): void
{
// Executed after global + auth + privacy middleware
}
#[SocketOn('public.message', excludeGlobalMiddlewares: [AuthMiddleware::class])]
public function handlePublicMessage(int $clientId, array $data): void
{
// Executed after global middleware except auth
}
}
HTTP Middleware
Middleware for HTTP requests follows the same pattern:
class ApiController extends SocketController
{
#[HttpRoute('POST', '/api/admin/users', middlewares: [AdminMiddleware::class])]
public function createAdminUser(Request $request): Response
{
// Executed after global + admin middleware
}
#[HttpRoute('GET', '/api/public/status', excludeGlobalMiddlewares: [AuthMiddleware::class])]
public function getPublicStatus(Request $request): Response
{
// Public endpoint - no auth required
}
}
Error Handling
WebSocket Error Responses
When a WebSocket handler throws an exception, the router automatically sends an error event:
// If this throws an exception:
#[SocketOn('risky.operation')]
public function riskyOperation(int $clientId, array $data): void
{
throw new Exception('Something went wrong');
}
// The client receives:
{
"event": "error",
"data": {
"message": "Something went wrong",
"code": 500
}
}
HTTP Error Responses
For HTTP routes, exceptions are converted to appropriate HTTP responses:
// If this throws an exception:
#[HttpRoute('GET', '/api/risky')]
public function riskyEndpoint(Request $request): Response
{
throw new Exception('Server error');
}
// Returns HTTP 500 with JSON error response
Complete Router Setup Example
<?php
use Sockeon\Sockeon\Core\Router;
use Sockeon\Sockeon\Connection\Server;
// Create server and router
$server = new Server();
$router = new Router($server);
// Add global middleware
$router->setGlobalMiddlewares([
LoggingMiddleware::class,
AuthenticationMiddleware::class
// Note: Rate limiting is handled automatically via #[RateLimit] attribute
]);
// Register controllers
$router->register(new ChatController());
$router->register(new UserController());
$router->register(new AdminController());
$router->register(new GameController());
// The router is now ready to handle events and requests
// The server will automatically use it for routing
// Start the server
$server->listen('0.0.0.0', 8080);
Advanced Routing Patterns
Nested Route Groups
While not directly supported, you can simulate route groups using consistent prefixes:
class ApiController extends SocketController
{
// User management routes
#[HttpRoute('GET', '/api/v1/users')]
public function listUsers(Request $request): Response { /* ... */ }
#[HttpRoute('POST', '/api/v1/users')]
public function createUser(Request $request): Response { /* ... */ }
#[HttpRoute('GET', '/api/v1/users/{id}')]
public function getUser(Request $request): Response { /* ... */ }
// Admin routes with additional middleware
#[HttpRoute('GET', '/api/v1/admin/users', middlewares: [AdminMiddleware::class])]
public function adminListUsers(Request $request): Response { /* ... */ }
#[HttpRoute('DELETE', '/api/v1/admin/users/{id}', middlewares: [AdminMiddleware::class])]
public function adminDeleteUser(Request $request): Response { /* ... */ }
}
Event Namespacing
Organize WebSocket events using dot notation:
class ChatController extends SocketController
{
// Room events
#[SocketOn('room.join')]
public function joinRoom(int $clientId, array $data): void { /* ... */ }
#[SocketOn('room.leave')]
public function leaveRoom(int $clientId, array $data): void { /* ... */ }
#[SocketOn('room.message')]
public function roomMessage(int $clientId, array $data): void { /* ... */ }
// User events
#[SocketOn('user.typing')]
public function userTyping(int $clientId, array $data): void { /* ... */ }
#[SocketOn('user.status')]
public function userStatus(int $clientId, array $data): void { /* ... */ }
// Admin events
#[SocketOn('admin.kick', middlewares: [AdminMiddleware::class])]
public function adminKick(int $clientId, array $data): void { /* ... */ }
#[SocketOn('admin.broadcast', middlewares: [AdminMiddleware::class])]
public function adminBroadcast(int $clientId, array $data): void { /* ... */ }
}
Performance Considerations
- Route Caching: Routes are cached in memory after initial scanning
- Middleware Efficiency: Keep middleware lightweight for better performance
- Controller Organization: Group related functionality in single controllers
- Error Handling: Use specific exceptions for better error reporting
See Also
- Controller API - Controller base class methods
- Middleware Guide - Creating custom middleware
- Routing Guide - Advanced routing patterns
- Server API - Server configuration and methods