Expand description
Type-safe data extraction from WebSocket messages and context.
This module provides a powerful type extraction system inspired by frameworks like Axum, allowing handlers to declaratively specify what data they need. Extractors automatically parse and validate data from messages, connection state, and application context.
§Overview
Extractors are types that implement the FromMessage trait. They can extract:
- Message content: JSON, binary data, text
- Connection info: Client address, connection ID, metadata
- Application state: Shared data like database pools, configuration
- Route parameters: Path and query parameters from routing
- Custom extensions: User-defined request-scoped data
§Design Philosophy
The extractor system follows these principles:
- Type safety: Extraction failures are caught at runtime with clear errors
- Composability: Multiple extractors can be used in a single handler
- Zero cost: Extraction happens only once per handler invocation
- Flexibility: Custom extractors can be easily implemented
§Built-in Extractors
| Extractor | Description | Example |
|---|---|---|
Json<T> | Deserialize JSON from message | Json(user): Json<User> |
State<T> | Extract shared application state | State(db): State<Arc<Database>> |
Connection | Get the active connection | conn: Connection |
ConnectInfo | Get connection metadata | ConnectInfo(info) |
Message | Get raw message | msg: Message |
Data | Extract binary data | Data(bytes) |
Path<T> | Extract path parameters | Path(id): Path<UserId> |
Query<T> | Extract query parameters | Query(params): Query<SearchParams> |
Extension<T> | Extract custom extensions | Extension(auth): Extension<Auth> |
§Examples
§Simple JSON Extraction
use wsforge::prelude::*;
use serde::Deserialize;
#[derive(Deserialize)]
struct ChatMessage {
username: String,
text: String,
}
async fn chat_handler(Json(msg): Json<ChatMessage>) -> Result<String> {
println!("{} says: {}", msg.username, msg.text);
Ok(format!("Message from {} received", msg.username))
}§Multiple Extractors
use wsforge::prelude::*;
use serde::Deserialize;
use std::sync::Arc;
#[derive(Deserialize)]
struct GameMove {
player: String,
action: String,
}
async fn game_handler(
Json(game_move): Json<GameMove>,
conn: Connection,
State(manager): State<Arc<ConnectionManager>>,
) -> Result<()> {
println!("Player {} from connection {} made move: {}",
game_move.player, conn.id(), game_move.action);
// Broadcast to other players
manager.broadcast_except(conn.id(),
Message::text(format!("{} moved", game_move.player)));
Ok(())
}§Custom Extractors
use wsforge::prelude::*;
use async_trait::async_trait;
// Custom extractor for authenticated users
struct AuthUser {
user_id: u64,
username: String,
}
#[async_trait]
impl FromMessage for AuthUser {
async fn from_message(
message: &Message,
conn: &Connection,
state: &AppState,
extensions: &Extensions,
) -> Result<Self> {
// Extract authentication token from message
let text = message.as_text()
.ok_or_else(|| Error::extractor("Message must be text"))?;
// Validate and extract user info
// (In production, verify JWT, session token, etc.)
Ok(AuthUser {
user_id: 123,
username: "user".to_string(),
})
}
}
async fn protected_handler(user: AuthUser) -> Result<String> {
Ok(format!("Hello, {}!", user.username))
}Structs§
- Connect
Info - Extractor for connection metadata.
- Data
- Extractor for raw binary data.
- Extension
- Extractor for custom extension data.
- Extensions
- Container for request-scoped extension data.
- Json
- Extractor for JSON data from messages.
- Path
- Extractor for path parameters.
- Query
- Extractor for query parameters.
- State
- Extractor for shared application state.
Traits§
- From
Message - Trait for types that can be extracted from WebSocket messages and context.