#actix-web Integration Guide

Version: 0.33.0 Updated: 2026-03-15 Applies to: ranvier-core, ranvier-macros, ranvier-runtime Category: Integration


Use Ranvier transitions in actix-web handlers and extractors.

#Overview

actix-web is a powerful, pragmatic, and extremely fast web framework for Rust. You can integrate Ranvier transitions into actix handlers to leverage both frameworks' strengths:

  • actix-web: Extractors, middleware, robust HTTP handling
  • Ranvier: Schematic visualization, Bus propagation, composable logic

#Integration Pattern

The recommended approach is to call Ranvier transitions from within actix handlers:

#Calling Ranvier Transition from actix Handler

use actix_web::{web, HttpRequest, HttpResponse};
use ranvier_core::{Bus, Outcome};
use ranvier_macros::transition;
use ranvier_runtime::Axon;

// Define your Ranvier transition
#[transition]
async fn process_order(
    order: Order,
    _res: &(),
    bus: &mut Bus
) -> Outcome<OrderResult, AppError> {
    // Your business logic here
    Outcome::Next(OrderResult { id: order.id, status: "processed" })
}

// actix handler
async fn create_order(
    req: HttpRequest,
    order: web::Json<Order>,
    pipeline: web::Data<Axon<Order, OrderResult, AppError, ()>>
) -> HttpResponse {
    let mut bus = Bus::new();

    // Optional: Extract auth from request and put in Bus
    if let Some(auth) = req.extensions().get::<AuthContext>() {
        bus.insert(auth.clone());
    }

    // Execute Ranvier pipeline
    match pipeline.execute(order.into_inner(), &(), &mut bus).await {
        Outcome::Next(result) => HttpResponse::Ok().json(result),
        Outcome::Fault(err) => HttpResponse::BadRequest().json(err),
        _ => HttpResponse::InternalServerError().finish(),
    }
}

// actix app setup
#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let pipeline = Axon::simple::<AppError>("order-pipeline")
        .then(process_order);

    HttpServer::new(move || {
        App::new()
            .app_data(web::Data::new(pipeline.clone()))
            .route("/orders", web::post().to(create_order))
    })
    .bind(("127.0.0.1", 8080))?
    .run()
    .await
}

#Using actix Extractors with Ranvier

use actix_web::{web, HttpResponse, Responder};
use actix_web_httpauth::extractors::bearer::BearerAuth;

async fn protected_handler(
    auth: BearerAuth,  // actix extractor
    data: web::Json<RequestData>,
    pipeline: web::Data<Axon<RequestData, ResponseData, AppError, ()>>
) -> impl Responder {
    let mut bus = Bus::new();

    // Put extracted token in Bus for Ranvier transitions
    bus.insert(auth.token().to_string());

    match pipeline.execute(data.into_inner(), &(), &mut bus).await {
        Outcome::Next(result) => HttpResponse::Ok().json(result),
        Outcome::Fault(err) => HttpResponse::Unauthorized().json(err),
        _ => HttpResponse::InternalServerError().finish(),
    }
}

#When to Use This Approach

Good for:

  1. Existing actix-web apps adding Ranvier for complex business logic
  2. Teams familiar with actix extractors and middleware
  3. Need actix's performance for HTTP handling
  4. Want Ranvier's Schematic visualization for business workflows

Consider:

  • Context bridging: You need to manually bridge actix request context (extractors) to Ranvier Bus
  • Middleware visibility: actix middleware won't appear in Ranvier Schematic
  • Testing: actix integration tests needed (unit test Ranvier transitions separately)

#Trade-offs

Aspect Benefit Limitation
Extractors Use actix's powerful extractors (Json, Query, Path, Auth) Manual bridging to Bus required
Middleware Leverage actix middleware ecosystem Not visible in Ranvier Schematic
Business Logic Ranvier transitions with Schematic visualization Extra boilerplate for actix-Ranvier integration
Performance actix's proven HTTP performance + Ranvier logic Minimal overhead from context bridging

#Comparison with Alternatives

  • vs Pure Ranvier: actix integration gives you actix extractors/middleware, but loses some Schematic visibility
  • vs Tower Integration: Similar pattern, but actix has different extractor model (function parameters vs request.extensions)
  • vs Axum Integration: actix uses trait-based extractors, Axum uses type-based extractors

  • Tower Integration โ€” Complete example available
  • Axum Integration โ€” Axum middleware with Ranvier