Extensions
Extensions, just like in Axum, allow you to store and share data throughout the lifecycle of an HTTP request. In Sword, they are especially useful for sharing information between web interceptors and controllers.
Web Controllers
Inserting data from an interceptor
A web interceptor can insert values into req.extensions before delegating execution to the next step in the pipeline.
use sword::prelude::*;
use sword::web::*;
use uuid::Uuid;
#[derive(Interceptor)]
struct RequestIdInterceptor;
impl OnRequest for RequestIdInterceptor {
async fn on_request(&self, mut req: Request) -> WebInterceptorResult {
let request_id = Uuid::new_v4();
req.extensions.insert::<Uuid>(request_id);
req.next().await
}
}Reading extensions from a controller
Next, a web controller can read that value from the same request:
use sword::prelude::*;
use sword::web::*;
use uuid::Uuid;
#[controller(kind = Controller::Web, path = "/api")]
#[interceptor(RequestIdInterceptor)]
struct ApiController;
impl ApiController {
#[get("/data")]
async fn get_data(&self, req: Request) -> JsonResponse {
let request_id = req.extensions.get::<Uuid>().cloned();
JsonResponse::Ok().data(serde_json::json!({
"request_id": request_id,
}))
}
}This pattern is useful for sharing:
- Request IDs.
- Authentication information.
- Flags calculated by interceptors or layers.
- Traceability context.
Request Mutability
If you need to insert or modify extensions within an interceptor, you must receive the request as mutable:
async fn on_request(&self, mut req: Request) -> WebInterceptorResultIf you only need to read extensions within the controller, the request doesn't need to be mutable.
Request and StreamRequest
Both Request and StreamRequest expose extensions. This allows you to reuse the same pattern even in streaming routes.
For example, a StreamRequest interceptor can insert data into req.extensions, and the handler can read it later.
Socket.IO Controllers
In Socket.IO, there's a related but distinct concept:
ctx.extensions()gives access to socket extensions.ctx.http_extensions()gives access to HTTP extensions associated with the initial handshake request.
This is useful when you need to share information between the HTTP handshake and the subsequent real-time event phase.
When to use extensions
Use extensions when you need to share state derived from a request or connection without making it a fixed dependency of the controller.
In contrast, if the data is structural or permanent in the application, it's usually better to model it as an injected dependency.

