#Tower Integration Guide
Version: 0.33.0 Updated: 2026-03-15 Applies to: ranvier (facade), ranvier-runtime, ranvier-http Category: Integration
Leverage Tower's Service/Layer ecosystem with Ranvier's Transition/Outcome/Bus paradigm.
#Overview
Tower is a library of modular and reusable components for building robust networking clients and servers. It provides the Service trait and Layer middleware abstraction, which powers many Rust web frameworks (Axum, Tonic, Hyper, etc.).
#Tower and Ranvier
Ranvier follows the "Opinionated Core, Flexible Edges" principle:
- Core (Opinionated): Transition/Outcome/Bus/Schematic paradigm is non-negotiable
- Edges (Flexible): Use Tower, actix, Axum, or any Rust tool at boundaries
This means you can use Tower's Service and Layer middleware alongside Ranvier transitions:
- Tower: Proven middleware for CORS, tracing, timeout, rate limiting, auth
- Ranvier: Schematic visualization, Bus propagation, composable transitions
#Integration Patterns
There are two main patterns for integrating Tower with Ranvier:
#Pattern 1: Tower Layers Wrapping Ranvier Handler
Use Tower layers for HTTP concerns (CORS, tracing, timeout) around Ranvier transitions:
use tower::ServiceBuilder;
use tower_http::{
cors::CorsLayer,
trace::TraceLayer,
timeout::TimeoutLayer,
};
let service = ServiceBuilder::new()
.layer(CorsLayer::permissive())
.layer(TraceLayer::new_for_http())
.layer(TimeoutLayer::new(Duration::from_secs(30)))
.service(ranvier_adapter); // โ Ranvier handlerWhen to use: You need battle-tested HTTP middleware (CORS, tracing)
#Pattern 2: Tower Service for Authentication
Use Tower's AsyncRequireAuthorizationLayer for authentication, then hand off to Ranvier:
use tower_http::auth::{AsyncAuthorizeRequest, AsyncRequireAuthorizationLayer};
#[derive(Clone)]
struct JwtAuthorizer { secret: String }
impl<B> AsyncAuthorizeRequest<B> for JwtAuthorizer {
type RequestBody = B;
type ResponseBody = String;
type Future = Ready<Result<Request<B>, Response<String>>>;
fn authorize(&mut self, mut request: Request<B>) -> Self::Future {
// JWT validation logic...
let auth_ctx = validate_jwt(token, &self.secret)?;
request.extensions_mut().insert(auth_ctx);
ready(Ok(request))
}
}
let service = ServiceBuilder::new()
.layer(AsyncRequireAuthorizationLayer::new(JwtAuthorizer { secret }))
.service(ranvier_adapter);When to use: You have existing Tower auth layers or need to integrate with Tower-based services
Both patterns are valid. Pattern 1 is simpler for HTTP concerns, while Pattern 2 gives you full control over request/response flow.
#Authentication Example Walkthrough
For a complete example, see examples/auth-tower-integration.
What it demonstrates:
- Two approaches: Manual Layer + Service implementation (educational) and high-level AsyncAuthorizeRequest trait (recommended)
- JWT validation: Tower layer validates JWT, stores AuthContext in request extensions
- Ranvier transitions: Business logic reads AuthContext from Bus (adapter extracts from extensions)
Key insight: Tower validates tokens โ stores AuthContext in request.extensions() โ Adapter extracts to Bus โ Ranvier transitions access from Bus.
Running the example:
cd examples/auth-tower-integration
cargo run
# Output:
# INFO Tower auth layer configured (JWT validation)
# INFO Ranvier pipeline configured (business logic)
# โ
Success: {"message":"Hello, alice! (Verified by Tower)",...}#When to Use Tower Integration
Good use cases:
- You have an existing Tower app and want to add Ranvier gradually
- Your team already knows Tower and wants to leverage that knowledge
- You need specific Tower middleware (CORS, rate limiting, compression)
- You're migrating from another framework (Axum, Tonic) that uses Tower
- You want battle-tested middleware without reimplementing it in Ranvier
Not recommended if:
- You're starting a new project and want full Schematic visualization (use pure Ranvier instead)
- You prioritize type-safe context propagation via Bus (Tower uses request extensions)
- You want to test transitions independently (Tower integration requires HTTP mocks)
For new projects, prefer Transition-based auth (
examples/auth-transition). It provides better Schematic visualization, Bus propagation, and testability. Use Tower integration for gradual migration from existing Tower apps.
#Trade-offs
| Aspect | Tower Integration | Pure Ranvier (Transition-based) |
|---|---|---|
| Ecosystem compatibility | Full access to Tower layers | Ranvier-specific |
| Schematic visualization | Tower layers are opaque | Full visibility in Circuit view |
| Context propagation | Request extensions (runtime) | Bus (compile-time type-safe) |
| Testing | Integration tests needed | Easy unit tests (inject Bus) |
| Team onboarding | Leverage Tower knowledge | Learn Ranvier paradigm |
| Boilerplate | 50-150 lines (Service trait) | 20 lines (transition macro) |
| Performance | Identical (zero-cost) | Identical (zero-cost) |
#Related Documents
- actix-web Integration โ actix extractors with Ranvier
- Axum Integration โ Axum middleware with Ranvier
- auth-comparison.md โ Transition vs Tower detailed comparison