Routes Structure
The Heimdall API is organized into a clean, hierarchical route structure with versioned endpoints.
Route Hierarchy
/ [Root - redirects to /v1]
/health [Health check - root level]
/v1 [API v1 info endpoint]
/v1/health [Health check - also available under v1]
/v1/auth/signin [POST - Sign in with API token]
/v1/auth/validate [POST - Validate API token]
/v1/gps [GET - List GPS data (paginated, authenticated)]
/v1/gps [POST - Create GPS data (admin only, rate-limited)]
/v1/gps/current [GET - Get current GPS (authenticated)]
/v1/gps/{id} [GET - Get GPS by ID (authenticated)]
/v1/settings [GET - Get all settings (admin only)]
/v1/settings/public [GET - Get public settings (no auth)]
/v1/settings/{key} [GET - Get setting by key (admin only)]
/v1/settings [POST - Create setting (admin only)]
/v1/settings/{key} [PUT - Update setting (admin only)]
/v1/settings/{key} [DELETE - Delete setting (admin only)]
/v1/stats/public [GET - Get public stats (no auth)]
/v1/ws [WS - WebSocket connection]
/v1/gql [POST/GET - GraphQL endpoint (authenticated)]
/v1/graphiql [GET - GraphiQL IDE (dev only, no auth)]
/v1/schema [GET - GraphQL schema SDL (no auth)]
/v1/api-keys [GET - List API keys (admin only)]
/v1/api-keys [POST - Create API key (admin only)]
/v1/api-keys/{id} [GET - Get API key by ID (admin only)]
/v1/api-keys/{id} [DELETE - Delete API key (admin only)]
/v1/roles [GET - List roles (admin only)]
/v1/roles [POST - Create role (admin only)]
/v1/roles/{id} [GET - Get role by ID (admin only)]
/v1/roles/{id} [PUT - Update role (admin only)]
/v1/roles/{id} [DELETE - Delete role (admin only)]
/v1/permissions [GET - List permissions (admin only)]
/v1/permissions [POST - Create permission (admin only)]
/v1/permissions/{id} [GET - Get permission by ID (admin only)]
/v1/permissions/{id} [PUT - Update permission (admin only)]
/v1/permissions/{id} [DELETE - Delete permission (admin only)]
/v1/users [GET - List users (admin only)]
/v1/users [POST - Create user (admin only)]
/v1/users/{id} [GET - Get user by ID (admin only)]
/v1/users/{id} [PUT - Update user (admin only)]
/v1/users/{id} [DELETE - Delete user (admin only)]
/v1/swagger-ui [GET - Redirect to /v1/swagger-ui/]
/v1/swagger-ui/ [GET - Swagger UI]
/v1/api-docs/openapi.json [GET - OpenAPI JSON specification]
Route Configuration Flow
main.rs
App::new()
.configure(routes::root_routes) // "/" and "/health"
.configure(routes::configure_public_routes) // Public routes under /v1
.service(
web::scope("/v1")
.configure(routes::configure_routes) // All authenticated v1 API routes
.configure(routes::configure_graphql) // GraphQL routes
)
// Swagger UI routes configured directly in main.rs
routes/mod.rs
Public Functions (called from main.rs):
root_routes()- Root endpoint (redirects to /v1)configure_public_routes()- Public routes including /health, /v1, /v1/healthconfigure_routes()- All authenticated v1 API routesconfigure_graphql()- GraphQL endpoints (/gql, /graphiql, /schema)
Route Modules (configured by configure_routes):
auth::configure- Authentication endpointsapi_keys::configure- API key managementroles::configure- Role managementpermissions::configure- Permission managementusers::configure- User managementgps::configure- GPS data endpointssettings::configure- Settings managementstats::configure- Statistics endpointswebsocket::configure- WebSocket endpoint
Authentication & Authorization
No Authentication Required
GET /- Root redirect to /v1GET /health- Health checkGET /v1- API infoGET /v1/health- Health checkGET /v1/settings/public- Public settingsGET /v1/stats/public- Public statisticsPOST /v1/auth/signin- Sign inPOST /v1/auth/validate- Validate tokenGET /v1/graphiql- GraphiQL IDE (development only)GET /v1/schema- GraphQL schema
Authentication Required (Any Authenticated User)
GET /v1/gps- List GPS dataGET /v1/gps/current- Current GPSGET /v1/gps/{id}- GPS by IDPOST /v1/gql- GraphQL endpointGET /v1/gql- GraphQL endpoint
Admin Only
POST /v1/gps- Create GPS (rate-limited: 30 req/60s)GET /v1/settings- All settingsGET /v1/settings/{key}- Setting by keyPOST /v1/settings- Create settingPUT /v1/settings/{key}- Update settingDELETE /v1/settings/{key}- Delete settingGET /v1/api-keys- List API keysPOST /v1/api-keys- Create API keyGET /v1/api-keys/{id}- Get API keyDELETE /v1/api-keys/{id}- Delete API keyGET /v1/roles- List rolesPOST /v1/roles- Create roleGET /v1/roles/{id}- Get rolePUT /v1/roles/{id}- Update roleDELETE /v1/roles/{id}- Delete roleGET /v1/permissions- List permissionsPOST /v1/permissions- Create permissionGET /v1/permissions/{id}- Get permissionPUT /v1/permissions/{id}- Update permissionDELETE /v1/permissions/{id}- Delete permissionGET /v1/users- List usersPOST /v1/users- Create userGET /v1/users/{id}- Get userPUT /v1/users/{id}- Update userDELETE /v1/users/{id}- Delete user
HATEOAS Links
All responses include _links with self-referencing URLs:
Single Resource:
{
"data": { ... },
"_links": {
"self": "https://api.example.com/v1/gps/abc-123"
}
}
Paginated Resource:
{
"data": [...],
"pagination": { ... },
"_links": {
"self": "https://api.example.com/v1/gps?page=2&limit=10",
"first": "https://api.example.com/v1/gps?page=1&limit=10",
"prev": "https://api.example.com/v1/gps?page=1&limit=10",
"next": "https://api.example.com/v1/gps?page=3&limit=10",
"last": "https://api.example.com/v1/gps?page=10&limit=10"
}
}
Middleware Stack
- CORS - Environment-aware (permissive in dev, strict in prod)
- Logger - HTTP request logging
- TracingLogger - Structured logging with tracing
- AuthMiddleware - Bearer token authentication (per-route)
- RequireRole - Role-based access control (per-route)
- RateLimitMiddleware - Rate limiting (per-route)
Benefits of This Structure
✅ Clear Separation: Root-level vs versioned API routes
✅ Scalable: Easy to add /v2 scope in the future
✅ Flexible Auth: Per-route authentication and authorization
✅ DRY: Reusable route configuration functions
✅ Type-Safe: Compile-time route verification
✅ HATEOAS: Self-documenting API with links