# lmrc-http-common
Common HTTP utilities and patterns for LMRC Stack applications.
This library provides reusable components for building Axum-based HTTP services with best practices built-in.
## Features
- **Error Handling**: Standard HTTP error types with automatic response conversion
- **Response Wrappers**: Success, created, empty, and paginated response types
- **Middleware**: CORS, logging, request ID, and more
- **Authentication** (optional): JWT, password hashing, session management
- **Configuration** Management: Server and database configuration loading
- **Health Checks**: Standardized health check framework
- **Validated Extractors** (optional): Auto-validate requests with `validator` crate
- **Server Bootstrap** (optional): Quick server setup with tracing and configuration
## Installation
Add to your `Cargo.toml`:
```toml
[dependencies]
lmrc-http-common = "0.3.11"
```
### Feature Flags
- `auth` (default) - Authentication utilities (JWT, bcrypt, sessions)
- `validation` (default) - Request validation helpers
- `server` - Server bootstrap utilities (requires `tracing-subscriber`, `dotenvy`)
To enable all features:
```toml
[dependencies]
lmrc-http-common = { version = "0.3.11", features = ["server"] }
```
## Quick Start
### Basic Handler with Error Handling
```rust
use lmrc_http_common::{
error::{HttpError, HttpResult},
response::SuccessResponse,
};
use axum::{Router, routing::get, Json};
async fn get_user(id: u32) -> HttpResult<Json<SuccessResponse<User>>> {
let user = database
.find_user(id)
.await
.ok_or_else(|| HttpError::NotFound(format!("User {} not found", id)))?;
Ok(Json(SuccessResponse::new(user)))
}
```
### Configuration Loading
```rust
use lmrc_http_common::config::{ServerConfig, DatabaseConfig};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Load configuration from environment variables
let server_config = ServerConfig::from_env()?;
let db_config = DatabaseConfig::from_env(None)?;
println!("Starting server on {}", server_config.bind_addr()?);
Ok(())
}
```
### Health Checks
```rust
use lmrc_http_common::health::{HealthChecker, HealthCheck, CheckResult};
use std::sync::Arc;
use async_trait::async_trait;
struct DatabaseHealthCheck {
db: DatabaseConnection,
}
#[async_trait]
impl HealthCheck for DatabaseHealthCheck {
async fn check(&self) -> CheckResult {
match self.db.ping().await {
Ok(_) => CheckResult::healthy_with_message("Database connected"),
Err(e) => CheckResult::unhealthy(format!("Database error: {}", e)),
}
}
fn name(&self) -> &str {
"database"
}
}
// In your router setup:
let checker = Arc::new(
HealthChecker::new(env!("CARGO_PKG_VERSION"))
.add_check(Arc::new(DatabaseHealthCheck { db }))
);
let app = Router::new()
.route("/health", get(lmrc_http_common::health::health_handler))
.with_state(checker);
```
### Validated Request Extractors
```rust
use lmrc_http_common::extractors::ValidatedJson;
use serde::Deserialize;
use validator::Validate;
#[derive(Deserialize, Validate)]
struct CreateUser {
#[validate(length(min = 3, max = 50))]
username: String,
#[validate(email)]
email: String,
}
async fn create_user(
ValidatedJson(payload): ValidatedJson<CreateUser>
) -> &'static str {
// payload is automatically validated!
// Returns 422 Unprocessable Entity if validation fails
"User created"
}
```
### Server Bootstrap (with `server` feature)
```rust
use axum::{Router, routing::get};
use lmrc_http_common::server::ServerBootstrap;
#[derive(Clone)]
struct AppState {
config: Config,
db: DatabaseConnection,
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let state = AppState {
config: Config::from_env()?,
db: DatabaseConnection::new().await?,
};
ServerBootstrap::with_state(state)
.with_tracing("myapp")
.with_port(8080)
.with_router(|state| {
Router::new()
.route("/health", get(|| async { "OK" }))
.with_state(state)
})
.serve()
.await
}
```
Or use the quick start helper:
```rust
use axum::{Router, routing::get};
use lmrc_http_common::server::quick_start;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let router = Router::new().route("/health", get(|| async { "OK" }));
quick_start("myapp", router, 8080).await
}
```
## Module Overview
### `error`
Standard HTTP error types that automatically convert to appropriate HTTP responses:
- `HttpError::BadRequest(String)` → 400
- `HttpError::Unauthorized(String)` → 401
- `HttpError::Forbidden(String)` → 403
- `HttpError::NotFound(String)` → 404
- `HttpError::ValidationError(String)` → 422
- `HttpError::InternalServer(String)` → 500
Use the `app_error!` macro to create custom error types:
```rust
use lmrc_http_common::app_error;
app_error! {
MyAppError {
BusinessLogic(String),
ExternalApi(String),
}
}
```
### `response`
Standard response wrappers:
- `SuccessResponse<T>` - Standard success response with data
- `CreatedResponse<T>` - 201 Created with location header
- `EmptyResponse` - 204 No Content
- `PaginatedResponse<T>` - Paginated list with metadata
### `middleware`
Reusable middleware layers:
- `add_request_id` - Adds unique request ID to each request
- `log_request` - Logs all requests with duration
- `cors_with_origins(Vec<String>)` - CORS with specific origins
### `config`
Configuration management:
- `ServerConfig` - Host, port, CORS origins
- `DatabaseConfig` - Database URL, connection pool settings
- `ConfigLoader` trait - For custom configuration types
### `health`
Health check framework:
- `HealthStatus` - Overall application health
- `HealthCheck` trait - Implement for custom checks
- `HealthChecker` - Aggregates multiple health checks
- `health_handler` - Axum handler for health endpoint
### `auth` (requires `auth` feature)
Authentication utilities:
- `jwt` - JWT token creation and verification
- `password` - Password hashing and verification (bcrypt)
- `session` - Session management
### `extractors` (requires `validation` feature)
Auto-validating request extractors:
- `ValidatedJson<T>` - JSON with automatic validation
- `ValidatedQuery<T>` - Query parameters with validation
### `server` (requires `server` feature)
Server bootstrap utilities:
- `ServerBootstrap` - Fluent API for server setup
- `quick_start` - Simple one-liner server start
## Examples
See the [examples directory](../../apps/lmrc-cli/embedded-apps/) for complete working examples:
- `gateway` - API gateway with routing and auth
- `api-service-template` - Standard REST API template
- `infra-api` - Infrastructure management API
## Development
### Running Tests
```bash
cargo test -p lmrc-http-common --all-features
```
### Building Documentation
```bash
cargo doc --open -p lmrc-http-common --all-features
```
## License
Dual licensed under MIT OR Apache-2.0 (your choice).
## Contributing
This library is part of the [LMRC Stack](https://gitlab.com/lemarco/lmrc-stack) monorepo.
See the main repository for contribution guidelines.