Attribute Macro request_scoped
#[request_scoped]Expand description
Define a request-scoped constructor.
Request-scoped constructors are invoked once per request to create a new instance of their output type. The created instance is cached for the duration of the request processing lifecycle.
Check out #[singleton] and #[transient]
if you need to define constructors with different lifecycles.
§Example
use pavex::methods;
pub struct RequestId(uuid::Uuid);
#[methods]
impl RequestId {
#[request_scoped]
pub fn new() -> Self {
Self(uuid::Uuid::new_v4())
}
}RequestId::new will be called once per request whenever a new instance of
RequestId is needed.
§Guide
Check out the “Dependency injection” section of Pavex’s guide for a thorough introduction to dependency injection in Pavex applications.
§Registration
You can register a request-scoped constructor with your application in two ways:
- Use
Blueprint::constructorto register a single constructor - Use
Blueprint::importto import multiple constructors in bulk
The #[request_scoped] macro generates a constant that you can use to refer to the
constructor when invoking Blueprint::constructor.
§Arguments
The sections below provide an exhaustive list of all the arguments and flags supported by the request_scoped macro:
| Name | Kind | Required |
|---|---|---|
id | Argument | No |
clone_if_necessary | Flag | No |
never_clone | Flag | No |
allow | Argument | No |
§id
By default, Pavex generates a constant named after your type and method (converted to UPPER_SNAKE_CASE) that you use when registering the constructor.
The id argument allows you to customize the name of the generated constant.
§Example
Using the default generated identifier:
use pavex::{methods, Blueprint};
pub struct RequestLogger {
// [...]
}
#[methods]
impl RequestLogger {
#[request_scoped]
pub fn new() -> Self {
Self {
// [...]
}
}
}
let mut bp = Blueprint::new();
// The generated constant is named `REQUEST_LOGGER_NEW`
bp.constructor(REQUEST_LOGGER_NEW);Using a custom identifier:
use pavex::{methods, Blueprint};
pub struct RequestLogger {
// [...]
}
#[methods]
impl RequestLogger {
#[request_scoped(id = "LOGGER_CONSTRUCTOR")]
// 👆 Custom identifier
pub fn new() -> Self {
Self {
// [...]
}
}
}
let mut bp = Blueprint::new();
// Use the custom identifier when registering
bp.constructor(LOGGER_CONSTRUCTOR);§clone_if_necessary
By default, Pavex will not clone the output of request-scoped constructors. The clone_if_necessary
flag allows Pavex to invoke .clone() on the output if it helps satisfy Rust’s borrow checker.
The constructed type must implement the Clone trait.
This flag is mutually exclusive with never_clone.
§Example
use pavex::methods;
use std::collections::HashMap;
#[derive(Clone)]
pub struct RequestConfig {
settings: HashMap<String, String>,
}
#[methods]
impl RequestConfig {
#[request_scoped(clone_if_necessary)]
// 👆 Allow cloning when needed
pub fn new() -> Self {
Self {
settings: HashMap::new(),
}
}
}§never_clone
The never_clone flag explicitly prevents Pavex from cloning the output of this constructor.
This is the default behavior for request-scoped constructors, so this flag is typically used
for clarity and explicitness.
This flag is mutually exclusive with clone_if_necessary.
§Example
use pavex::methods;
pub struct ScratchPad {
// Contains non-cloneable resources
temp_file: std::fs::File,
}
#[methods]
impl ScratchPad {
#[request_scoped(never_clone)]
// 👆 Explicitly prevent cloning (default behavior)
pub fn new() -> std::io::Result<Self> {
Ok(Self {
temp_file: std::fs::File::create("request.tmp")?,
})
}
}Pavex will report an error during the code-generation phase if cloning is required but forbidden.
§allow
The allow argument can be used to suppress specific warnings.
Currently, only one value is supported:
unused: Suppress warnings if this constructor is registered but never used
§Example
use pavex::methods;
pub struct DebugInfo {
// [...]
}
#[methods]
impl DebugInfo {
#[request_scoped(allow(unused))]
// 👆 Don't warn if unused
pub fn new() -> Self {
Self {
// [...]
}
}
}