Armature
A modern, type-safe HTTP framework for Rust heavily inspired by **Angular** and **NestJS**.
Install / Use
/learn @pegasusheavy/ArmatureREADME
Armature 🦾
A modern, type-safe HTTP framework for Rust heavily inspired by Angular and NestJS.
Armature brings the elegant decorator syntax and powerful dependency injection from the TypeScript/JavaScript ecosystem to Rust, combining the developer experience of NestJS with Rust's performance and safety guarantees.
Features
- Completely Stateless: No server-side sessions, fully stateless JWT-based authentication
- Decorator Syntax: Use Angular-style decorators via procedural macros
- Full Dependency Injection: Automatic service injection into controllers based on field types
- Type-Safe DI Container: Compile-time verified dependency resolution
- Modular Architecture: Organize your application into modules with providers and controllers
- Service Dependencies: Services can depend on other services with automatic resolution
- Singleton Pattern: Services are created once and shared across the application
- Lifecycle Hooks: NestJS-style hooks (OnModuleInit, OnModuleDestroy, OnApplicationBootstrap, OnApplicationShutdown) for resource management
- Authentication & Authorization: Optional comprehensive auth system with guards, RBAC, and strategies
- OAuth2/OIDC Providers: Built-in support for Google, Microsoft, AWS Cognito, Okta, and Auth0
- SAML 2.0 Support: Enterprise SSO with Service Provider implementation
- Password Hashing: Bcrypt and Argon2 support with auto-detection
- JWT Authentication: Optional JWT token management with HS256/RS256/ES256 support
- Configuration Management: Optional NestJS-style config system with env, .env, JSON, and TOML support
- GraphQL Support: Optional type-safe GraphQL API with queries, mutations, and subscriptions
- Rate Limiting: Token bucket, sliding window, and fixed window algorithms with Redis support
- Response Compression: Automatic gzip, brotli, and zstd compression with content-type awareness
- Comprehensive Logging: Highly configurable structured logging with JSON/Pretty/Plain formats, multiple outputs, and HTTP middleware
- Testing Utilities: Comprehensive testing framework with mocks, spies, and assertions
- Validation Framework: Powerful validation with built-in validators and custom rules
- WebSocket Support: Full-duplex real-time communication with rooms and broadcasting
- Server-Sent Events (SSE): Efficient server-to-client streaming for live updates
- HTTPS/TLS Support: Built-in TLS support with certificate management and automatic HTTP to HTTPS redirect
- OpenTelemetry Integration: Distributed tracing, metrics, and observability with OTLP, Jaeger, Zipkin, and Prometheus support
- Async-First: Built on Tokio and Hyper for high-performance async I/O
- Type-Safe Routing: Path parameters and query string parsing with compile-time validation
- JSON Serialization: Built-in support for JSON request/response handling
Quick Start
Using the CLI (Recommended)
Install the Armature CLI for the best development experience:
# Install the CLI
cargo install armature-cli
# Create a new project
armature new my-api
# Navigate to your project
cd my-api
# Start the development server with hot reloading
armature dev
Generate Code
# Generate a controller
armature generate controller users
# Generate a service
armature generate service users
# Generate a complete resource (controller + service + module)
armature generate resource products --crud
# Generate middleware, guards, and more
armature generate middleware auth
armature generate guard admin
Manual Setup
use armature_framework::prelude::*;
use serde::{Deserialize, Serialize};
// Define your domain model
#[derive(Serialize, Deserialize)]
struct User {
id: u32,
name: String,
}
// Create an injectable service
#[injectable]
#[derive(Default, Clone)]
struct DatabaseService;
#[injectable]
#[derive(Default, Clone)]
struct UserService {
database: DatabaseService, // Automatically injected!
}
impl UserService {
fn get_users(&self) -> Vec<User> {
vec![User { id: 1, name: "Alice".to_string() }]
}
}
// Create a controller with automatic DI
#[controller("/users")]
#[derive(Default, Clone)]
struct UserController {
user_service: UserService, // Automatically injected!
}
impl UserController {
// Use injected service in methods
fn get_all(&self) -> Result<Json<Vec<User>>, Error> {
Ok(Json(self.user_service.get_users()))
}
fn get_one(&self, id: u32) -> Result<Json<User>, Error> {
// Use self.user_service throughout the controller
Ok(Json(User { id, name: "Alice".to_string() }))
}
}
// Define your application module
#[module(
providers: [DatabaseService, UserService],
controllers: [UserController]
)]
#[derive(Default)]
struct AppModule;
// Bootstrap your application - DI happens automatically!
#[tokio::main]
async fn main() {
let app = Application::create::<AppModule>();
app.listen(3000).await.unwrap();
}
Architecture
The framework is organized into three main crates:
armature-core
Core runtime functionality including:
- Traits (
Provider,Controller,Module,RequestHandler) - DI Container with type-based resolution
- Router with path parameter extraction
- HTTP request/response types
- Error handling
armature-macro
Procedural macros for decorator syntax:
#[injectable]- Mark structs as injectable services#[controller("/path")]- Define controllers with base paths#[get],#[post],#[put],#[delete],#[patch]- HTTP route decorators#[module(...)]- Organize components into modules#[derive(Body)],#[derive(Param)],#[derive(Query)]- Request parameter extraction
armature-framework
Main library that re-exports everything from core and macros. Add to your Cargo.toml:
[dependencies]
armature-framework = "0.1"
Or with specific features:
[dependencies]
armature-framework = { version = "0.1", features = ["auth", "cache", "validation"] }
Decorators
Service Decorators
#[injectable]
Marks a struct as injectable, allowing it to be registered in the DI container:
#[injectable]
struct DatabaseService {
connection: DbConnection,
}
Controller Decorators
#[controller("/path")]
Marks a struct as a controller with a base path:
#[controller("/api/users")]
struct UserController {
user_service: UserService,
}
Route Decorators
HTTP method decorators for defining routes:
#[get("/")] // GET /api/users/
#[get("/:id")] // GET /api/users/:id
#[post("/")] // POST /api/users/
#[put("/:id")] // PUT /api/users/:id
#[delete("/:id")] // DELETE /api/users/:id
#[patch("/:id")] // PATCH /api/users/:id
Module Decorator
#[module(...)]
Defines a module with providers, controllers, and imports:
#[module(
providers: [UserService, DatabaseService],
controllers: [UserController],
imports: [CommonModule],
exports: [UserService]
)]
struct UserModule;
Dependency Injection
The DI container uses Rust's type system for service resolution:
// Register a service
container.register(MyService::default());
// Resolve a service
let service = container.resolve::<MyService>()?;
Services are singletons by default and shared across the application.
Lifecycle Hooks
Armature provides NestJS-inspired lifecycle hooks for managing service initialization and cleanup:
use armature_framework::prelude::*;
use armature_framework::lifecycle::{OnModuleInit, OnModuleDestroy, LifecycleResult};
use async_trait::async_trait;
#[injectable]
struct DatabaseService {
connected: Arc<RwLock<bool>>,
}
#[async_trait]
impl OnModuleInit for DatabaseService {
async fn on_module_init(&self) -> LifecycleResult {
println!("Connecting to database...");
*self.connected.write().await = true;
Ok(())
}
}
#[async_trait]
impl OnModuleDestroy for DatabaseService {
async fn on_module_destroy(&self) -> LifecycleResult {
println!("Closing database connection...");
*self.connected.write().await = false;
Ok(())
}
}
Available hooks:
OnModuleInit- Called after module initializationOnModuleDestroy- Called before module destructionOnApplicationBootstrap- Called after full application bootstrapOnApplicationShutdown- Called during graceful shutdownBeforeApplicationShutdown- Called before shutdown hooks
See the Lifecycle Hooks Guide for complete documentation.
Routing
The router supports:
- Static paths:
/users - Path parameters:
/users/:id - Query parameters:
/users?page=1&limit=10 - Multiple HTTP methods per route
Path parameters are extracted automatically:
#[get("/:id")]
async fn get_user(req: HttpRequest) -> Result<Json<User>, Error> {
let id = req.param("id").unwrap();
// ...
}
HTTP Status Codes and Error Handling
Comprehensive HTTP status code support with type-safe error handling:
use armature_framework::{Error, HttpStatus};
// Type-safe status codes
let status = HttpStatus::NotFound;
assert_eq!(status.code(), 404);
assert_eq!(status.reason(), "Not Found");
// Structured errors for all 4xx/5xx codes
return Err(Error::NotFound("User not found".to_string()));
return Err(Error::TooManyRequests("Rate limit exceeded".to_string()));
return Err(Error::ServiceUnavailable("Database down".to_string()));
// Error helpers
let error = Error::Unauthorized("Invalid token".to_string());
assert_eq!(error.status_code(), 401);
assert!(error.is_client_error());
See the HTTP Status & Errors Guide for complete documentation.
Guards and Interceptors
Protect and transform your routes with Guards and Interceptors:
use armature_framework::{Guard, AuthenticationGuard, Gu
Related Skills
node-connect
353.1kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
111.6kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
353.1kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
353.1kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
