PluginBench
Skill
Pass
Audit score 90

domain-web

actionbook/rust-skills

Build concurrent, type-safe web services with async handlers, middleware, and shared state patterns.

What is domain-web?

A domain-layer skill for Rust web development that enforces constraints around async handlers, thread-safe state management, and request lifecycle. Use when designing REST APIs, GraphQL servers, or WebSocket services with frameworks like axum, actix-web, warp, or rocket.

  • Enforce async-first handler design to prevent blocking and latency spikes
  • Guide thread-safe shared state patterns using Arc and Arc<RwLock<T>>
  • Provide extractor-based request validation and parsing
  • Structure error handling via IntoResponse trait implementations
  • Compose middleware stacks with Tower layers for cross-cutting concerns
  • Map domain constraints to Rust type system and ownership rules

How to install domain-web

npx skills add https://github.com/actionbook/rust-skills --skill domain-web
Claude Code
Cursor
Windsurf
Cline

How to use domain-web

  1. 1.Identify your web framework (axum, actix-web, warp, or rocket) and review its handler signature
  2. 2.Structure shared state as Arc<AppState> and pass via State extractor
  3. 3.Define request types as serde-deserializable structs for type-safe extraction
  4. 4.Implement IntoResponse for your error type to unify error responses
  5. 5.Use Tower layers for middleware (logging, auth, CORS, rate limiting)
  6. 6.Spawn blocking operations with spawn_blocking rather than blocking in handlers

Use cases

Good for
  • Building a REST API with validated request extractors and unified error responses
  • Implementing shared application state (database pools, caches) across concurrent handlers
  • Designing middleware chains for authentication, logging, and rate limiting
  • Migrating blocking code to async with spawn_blocking for CPU-bound work
  • Choosing between axum, actix-web, warp, and rocket based on performance and API style needs
Who it's for
  • Backend engineers building HTTP services or APIs
  • Rust developers new to async web frameworks
  • Teams standardizing on web domain patterns and constraints

domain-web FAQ

When should I use Arc<RwLock<T>> vs Arc<T> for shared state?

Use Arc<T> for immutable state; use Arc<RwLock<T>> only when handlers need to mutate shared data. Prefer immutable patterns and message-passing where possible to avoid lock contention.

How do I prevent blocking in async handlers?

Use spawn_blocking for CPU-bound work (compression, hashing) and ensure all I/O is async. Blocking in a handler blocks all tasks on that thread, degrading latency for other requests.

What's the difference between extractors and middleware?

Extractors parse and validate individual request data (State, Json, Path); middleware runs on every request in a stack and handles cross-cutting concerns (logging, auth, CORS).

How do I choose between axum, actix-web, warp, and rocket?

axum is modern and tower-based; actix-web prioritizes performance; warp emphasizes composable filters; rocket favors rapid development with macros. Match your team's preference and performance needs.

Should I validate in extractors or in handler logic?

Validate in extractors using type-safe deserialization and custom extractor implementations. This prevents invalid data from reaching handlers and centralizes validation logic.

Full instructions (SKILL.md)

Source of truth, from actionbook/rust-skills.


name: domain-web description: "Use when building web services. Keywords: web server, HTTP, REST API, GraphQL, WebSocket, axum, actix, warp, rocket, tower, hyper, reqwest, middleware, router, handler, extractor, state management, authentication, authorization, JWT, session, cookie, CORS, rate limiting, web 开发, HTTP 服务, API 设计, 中间件, 路由" globs: ["**/Cargo.toml"] user-invocable: false

Web Domain

Layer 3: Domain Constraints

Domain Constraints → Design Implications

Domain RuleDesign ConstraintRust Implication
Stateless HTTPNo request-local globalsState in extractors
ConcurrencyHandle many connectionsAsync, Send + Sync
Latency SLAFast responseEfficient ownership
SecurityInput validationType-safe extractors
ObservabilityRequest tracingtracing + tower layers

Critical Constraints

Async by Default

RULE: Web handlers must not block
WHY: Block one task = block many requests
RUST: async/await, spawn_blocking for CPU work

State Management

RULE: Shared state must be thread-safe
WHY: Handlers run on any thread
RUST: Arc<T>, Arc<RwLock<T>> for mutable

Request Lifecycle

RULE: Resources live only for request duration
WHY: Memory management, no leaks
RUST: Extractors, proper ownership

Trace Down ↓

From constraints to design (Layer 2):

"Need shared application state"
    ↓ m07-concurrency: Use Arc for thread-safe sharing
    ↓ m02-resource: Arc<RwLock<T>> for mutable state

"Need request validation"
    ↓ m05-type-driven: Validated extractors
    ↓ m06-error-handling: IntoResponse for errors

"Need middleware stack"
    ↓ m12-lifecycle: Tower layers
    ↓ m04-zero-cost: Trait-based composition

Framework Comparison

FrameworkStyleBest For
axumFunctional, towerModern APIs
actix-webActor-basedHigh performance
warpFilter compositionComposable APIs
rocketMacro-drivenRapid development

Key Crates

PurposeCrate
HTTP serveraxum, actix-web
HTTP clientreqwest
JSONserde_json
Auth/JWTjsonwebtoken
Sessiontower-sessions
Databasesqlx, diesel
Middlewaretower

Design Patterns

PatternPurposeImplementation
ExtractorsRequest parsingState(db), Json(payload)
Error responseUnified errorsimpl IntoResponse
MiddlewareCross-cuttingTower layers
Shared stateApp configArc<AppState>

Code Pattern: Axum Handler

async fn handler(
    State(db): State<Arc<DbPool>>,
    Json(payload): Json<CreateUser>,
) -> Result<Json<User>, AppError> {
    let user = db.create_user(&payload).await?;
    Ok(Json(user))
}

// Error handling
impl IntoResponse for AppError {
    fn into_response(self) -> Response {
        let (status, message) = match self {
            Self::NotFound => (StatusCode::NOT_FOUND, "Not found"),
            Self::Internal(_) => (StatusCode::INTERNAL_SERVER_ERROR, "Internal error"),
        };
        (status, Json(json!({"error": message}))).into_response()
    }
}

Common Mistakes

MistakeDomain ViolationFix
Blocking in handlerLatency spikespawn_blocking
Rc in stateNot Send + SyncUse Arc
No validationSecurity riskType-safe extractors
No error responseBad UXIntoResponse impl

Trace to Layer 1

ConstraintLayer 2 PatternLayer 1 Implementation
Async handlersAsync/awaittokio runtime
Thread-safe stateShared stateArc<T>, Arc<RwLock<T>>
Request lifecycleExtractorsOwnership via From<Request>
MiddlewareTower layersTrait-based composition

Related Skills

WhenSee
Async patternsm07-concurrency
State managementm02-resource
Error handlingm06-error-handling
Middleware designm12-lifecycle