Route Groups Guide
Comprehensive guide to organizing routes with Route Groups in Armature.
Table of Contents
- Overview
- Features
- Basic Usage
- Shared Configuration
- Nested Groups
- Best Practices
- API Reference
- Examples
- Summary
Overview
Route Groups allow you to organize routes with shared configuration, making your routing code more maintainable and DRY (Don't Repeat Yourself).
Route groups provide:
- Path prefixes - Automatic prefix for all routes in the group
- Shared middleware - Apply middleware to all routes in the group
- Shared guards - Apply authorization to all routes in the group
- Nested configuration - Groups can inherit from parent groups
Features
- โ Path prefix inheritance
- โ Shared middleware application
- โ Shared guard application
- โ Nested groups with configuration merging
- โ Fluent builder API
- โ Type-safe configuration
Basic Usage
Creating a Route Group
use armature_core::*;
// Create a basic API group with prefix
let api_group = RouteGroup::new()
.prefix("/api/v1");
// All routes in this group will have /api/v1 prefix
let user_route = api_group.apply_prefix("/users");
// Result: "/api/v1/users"
With Middleware
use armature_core::*;
use std::sync::Arc;
let api_group = RouteGroup::new()
.prefix("/api/v1")
.middleware(Arc::new(LoggerMiddleware))
.middleware(Arc::new(CorsMiddleware::default()));
// All routes in this group will have logging and CORS enabled
With Guards
use armature_core::*;
let protected_group = RouteGroup::new()
.prefix("/api/v1/admin")
.guard(Box::new(AuthenticationGuard))
.guard(Box::new(RolesGuard::new(vec!["admin".to_string()])));
// All routes require authentication AND admin role
Shared Configuration
Path Prefixes
Route groups automatically prepend prefixes to all routes:
use armature_core::*;
let api = RouteGroup::new().prefix("/api/v1");
// Apply prefix to routes
assert_eq!(api.apply_prefix("/users"), "/api/v1/users");
assert_eq!(api.apply_prefix("/posts"), "/api/v1/posts");
assert_eq!(api.apply_prefix("/comments"), "/api/v1/comments");
Multiple Middleware
Middleware are applied in the order they're added:
let group = RouteGroup::new()
.middleware(Arc::new(LoggerMiddleware))
.middleware(Arc::new(CorsMiddleware::default()))
.middleware(Arc::new(CompressionMiddleware::new()));
// Execution order: Logger โ CORS โ Compression โ Handler
Multiple Guards
All guards must pass for access to be granted (AND logic):
let group = RouteGroup::new()
.guard(Box::new(AuthenticationGuard))
.guard(Box::new(RolesGuard::new(vec!["admin".to_string()])))
.guard(Box::new(ApiKeyGuard::new(vec!["key123".to_string()])));
// Request must pass ALL guards
Nested Groups
Groups can inherit configuration from parent groups:
Basic Nesting
use armature_core::*;
let api = RouteGroup::new()
.prefix("/api")
.middleware(Arc::new(LoggerMiddleware));
let v1 = RouteGroup::new()
.prefix("/v1")
.with_parent(&api);
// v1 inherits:
// - Prefix: "/api/v1"
// - Middleware: LoggerMiddleware
let admin = RouteGroup::new()
.prefix("/admin")
.guard(Box::new(AdminGuard))
.with_parent(&v1);
// admin inherits:
// - Prefix: "/api/v1/admin"
// - Middleware: LoggerMiddleware
// - Guard: AdminGuard
Configuration Merging Rules
When using with_parent():
- Prefixes are concatenated - parent prefix + child prefix
- Middleware are combined - parent middleware execute first
- Guards are from child only - cannot clone Box
Best Practices
1. Organize by API Version
let v1 = RouteGroup::new()
.prefix("/api/v1")
.middleware(Arc::new(LoggerMiddleware));
let v2 = RouteGroup::new()
.prefix("/api/v2")
.middleware(Arc::new(LoggerMiddleware))
.middleware(Arc::new(RateLimitMiddleware::new()));
2. Group by Authentication Level
let public = RouteGroup::new()
.prefix("/api/public");
let authenticated = RouteGroup::new()
.prefix("/api/auth")
.guard(Box::new(AuthenticationGuard));
let admin = RouteGroup::new()
.prefix("/api/admin")
.guard(Box::new(AuthenticationGuard))
.guard(Box::new(AdminGuard));
3. Combine Strategies
// Base API group
let api = RouteGroup::new()
.prefix("/api")
.middleware(Arc::new(LoggerMiddleware));
// Version groups
let v1 = RouteGroup::new()
.prefix("/v1")
.with_parent(&api);
// Resource groups within v1
let v1_users = RouteGroup::new()
.prefix("/users")
.guard(Box::new(AuthenticationGuard))
.with_parent(&v1);
let v1_admin = RouteGroup::new()
.prefix("/admin")
.guard(Box::new(AuthenticationGuard))
.guard(Box::new(AdminGuard))
.with_parent(&v1);
API Reference
RouteGroup Methods
| Method | Description |
|---|---|
prefix(path) |
Set the path prefix for this group |
middleware(mw) |
Add a single middleware |
with_middleware(mws) |
Add multiple middleware |
guard(guard) |
Add a single guard |
with_guards(guards) |
Add multiple guards |
get_prefix() |
Get the current prefix |
apply_prefix(path) |
Apply prefix to a path |
get_middleware() |
Get all middleware |
get_guards() |
Get all guards |
with_parent(parent) |
Inherit from parent group |
Summary
Key Points:
- RouteGroup organizes routes with shared configuration
- Prefixes are automatically applied and normalized
- Middleware stack in order they're added
- All guards must pass (AND logic)
- Nest groups with
with_parent()for inheritance - Use for API versions, auth levels, resources
Quick Reference:
// Basic group
let group = RouteGroup::new()
.prefix("/api/v1")
.middleware(Arc::new(LoggerMiddleware))
.guard(Box::new(AuthenticationGuard));
// Nested group
let child = RouteGroup::new()
.prefix("/admin")
.guard(Box::new(AdminGuard))
.with_parent(&group);
// Apply prefix
let path = child.apply_prefix("/users");
// Result: "/api/v1/admin/users"
Benefits:
- ๐ฆ DRY - Don't repeat middleware/guards
- ๐ฏ Organized - Clear route structure
- ๐ Secure - Consistent auth application
- ๐ Scalable - Easy to add new groups
- ๐ง Maintainable - Change once, apply everywhere