dog-axum
A high-level REST framework built on Axum that provides service-oriented architecture with pluggable middleware support.
Features
- Service-oriented REST API - Clean separation between routes and business logic
- Pluggable middleware - Apply middleware per service or globally
- Multipart upload support - Built-in middleware for handling file uploads with BlobRef pattern
- Framework-safe patterns - Memory-efficient handling of large files
- Tower ecosystem integration - Full compatibility with Tower middleware
Optional integration features
auth
Enable dog-axum's auth feature to integrate with dog-auth hook params.
This adds FromRestParams support for:
dog_auth::hooks::authenticate::AuthParams<dog_axum::params::RestParams>
so application code can simply use:
pub type Params = AuthParams;
without writing boilerplate conversion code.
OAuth DX helpers
dog-axum includes small, provider-agnostic helpers that make it easier to expose OAuth flows over HTTP.
REST helpers (in dog_axum::rest):
call_custom_json/call_custom_redirectcall_custom_json_q/call_custom_json_qdcall_custom_redirect_q/call_custom_redirect_qdcall_custom_redirect_location(defaultslocation_keyto"location")oauth_callback_capture_typed(standard capture response for service-mode callback testing)
Route builder (in dog_axum::oauth):
OAuthRoutesmount_oauth_routes
These helpers are intentionally policy-free: you provide the service name, custom method names, paths, and callback payload shape.
Quick Start
1. Basic REST Server
Create a minimal dog-axum server:
use AxumApp;
use ;
use Arc;
// Define your request/response types
// Create a service
;
// Build the server
async
2. Adding Middleware
Apply middleware to specific services:
use ;
use ServiceBuilder;
let server = new
// Single middleware
.use_service_with
// Multiple middleware with ServiceBuilder
.use_service_with
// Service without middleware
.use_service;
3. Global Middleware
Apply middleware to all routes:
let mut server = new
.use_service
.use_service;
// Add global middleware to the router
server.router = server.router
.layer
.layer;
Middleware
Built-in Middleware
MultipartToJson
Handles multipart form uploads and converts them to JSON with BlobRef pattern for files:
use ;
let config = default
.with_max_file_size // 50MB per file
.with_max_total_size; // 200MB total
let server = new
.use_service_with;
BlobRef Pattern: Files are streamed to temporary storage and services receive references:
Visual BlobRef Flow:
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Multipart │ │ MultipartToJson│ │ Temp Storage │ │ Service │
│ Upload │───▶│ Middleware │───▶│ /tmp/file_* │───▶│ Gets BlobRef │
│ (7MB file) │ │ │ │ │ │ (not raw data) │
└─────────────────┘ └─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Streams chunks │ │ File written to │ │ JSON with │
│ (no memory │ │ disk (not RAM) │ │ file reference │
│ buffering) │ │ │ │ (framework-safe)│
└─────────────────┘ └─────────────────┘ └─────────────────┘
// Service receives this JSON structure for file uploads:
// Your service can then process the file:
Custom Middleware
Create custom middleware using Tower patterns:
use ;
use ;
;
Middleware Execution Order
Middleware executes in reverse order of how it's added:
new
.layer // Executes 1st (outermost)
.layer // Executes 2nd
.layer // Executes 3rd
.layer // Executes 4th (innermost)
Visual Request Flow:
┌─────────────┐ ┌──────────────┐ ┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Request │───▶│ CORS Layer │───▶│ Auth Layer │───▶│ RateLimit │───▶│ Multipart │
│ (Client) │ │ (Outermost) │ │ │ │ Layer │ │ Layer │
└─────────────┘ └──────────────┘ └─────────────┘ └──────────────┘ └─────────────┘
│
▼
┌─────────────┐ ┌──────────────┐ ┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Response │◀───│ CORS Layer │◀───│ Auth Layer │◀───│ RateLimit │◀───│ Service │
│ (Client) │ │ │ │ │ │ Layer │ │ (Business) │
└─────────────┘ └──────────────┘ └─────────────┘ └──────────────┘ └─────────────┘
Examples
See the dog-examples/ directory for complete examples:
- music-blobs: File upload service with multipart middleware
- blog-axum: Basic REST API with CRUD operations
- social-typedb: Complex service with authentication middleware
Dependencies
Add to your Cargo.toml:
[]
= "0.1.0"
= "0.1.0"
= "0.7"
= "0.4"
= { = "1.0", = ["full"] }
= { = "1.0", = ["derive"] }
Architecture
dog-axum provides a service-oriented architecture where:
- Services implement business logic (
DogServicetrait) - Routes are automatically generated for CRUD operations
- Middleware can be applied per-service or globally
- Request/Response types are strongly typed with serde
Visual Architecture:
┌─────────────────────────────────────────────────────────────────────────────────────┐
│ dog-axum │
├─────────────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Client │───▶│ Router │───▶│ Middleware │───▶│ Service │ │
│ │ (HTTP Req) │ │ (Axum) │ │ (Tower) │ │ (Business) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Auto Routes │ │ Per-Service │ │ Typed Data │ │
│ │ GET/POST/ │ │ or Global │ │ Serde JSON │ │
│ │ PUT/DELETE │ │ Layers │ │ Validation │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
├─────────────────────────────────────────────────────────────────────────────────────┤
│ Built on Tower + Axum │
└─────────────────────────────────────────────────────────────────────────────────────┘
Service Registration Flow:
AxumApp::new(app)
│
├─ .use_service("/users", user_service)
│ └─ Creates: GET/POST/PUT/DELETE /users routes
│
├─ .use_service_with("/upload", upload_service, MultipartToJson)
│ └─ Creates: Routes + applies middleware to this service only
│
└─ .service("/health", health_handler)
└─ Creates: Custom route with handler function
This separation allows for clean, testable code with flexible middleware composition.