pavex/lib.rs
1//! # Pavex - API reference
2//!
3//! Welcome to the API reference for Pavex!
4//!
5//! The API reference is fairly low-level.\
6//! If you want a high-level overview of Pavex, check out the [documentation](https://pavex.dev/docs/)
7//! on Pavex's website.\
8//! You'll also find [an installation guide](https://pavex.dev/docs/getting_started/) as well as a
9//! [quickstart tutorial](https://pavex.dev/docs/getting_started/quickstart/)
10//! to get you up and running with the framework in no time.
11
12pub use error::error_::Error;
13
14pub use blueprint::blueprint::Blueprint;
15pub use response::{into_response::IntoResponse, response_::Response};
16
17pub mod blueprint;
18#[cfg(feature = "config")]
19pub mod config;
20pub mod connection;
21#[cfg(feature = "cookie")]
22pub mod cookie;
23pub mod error;
24pub mod http;
25pub mod middleware;
26pub mod request;
27pub mod response;
28pub mod router;
29pub mod serialization;
30#[cfg(feature = "server")]
31pub mod server;
32pub mod telemetry;
33pub mod unit;
34#[cfg(feature = "time")]
35pub mod time {
36 //! Utilities to work with dates, timestamps and datetimes.
37 //!
38 //! It's a re-export of the [`jiff@0.2`](https://docs.rs/jiff/0.2) crate.
39 pub use jiff::*;
40}
41
42/// Define a [prebuilt type](https://pavex.dev/docs/guide/dependency_injection/prebuilt_types/).
43///
44/// Prebuilt types are constructed outside of Pavex's dependency injection framework
45/// but can still be injected as dependencies into your components.
46///
47/// # Example
48///
49/// ```rust
50/// use pavex::prebuilt;
51///
52/// #[prebuilt]
53/// #[derive(Debug)]
54/// pub struct DatabaseConnectionPool {
55/// // Connection pool initialized elsewhere
56/// }
57/// ```
58///
59/// # Guide
60///
61/// Check out the ["Dependency injection"](https://pavex.dev/docs/guide/dependency_injection)
62/// section of Pavex's guide for a thorough introduction to dependency injection
63/// in Pavex applications.
64///
65/// # Registration
66///
67/// You can register a prebuilt type with your application in two ways:
68/// - Use [`Blueprint::prebuilt`] to register a single prebuilt type
69/// - Use [`Blueprint::import`] to import multiple prebuilt types in bulk
70///
71/// The `#[prebuilt]` macro [generates a constant](#id) that you can use to refer to a specific
72/// prebuilt type when invoking [`Blueprint::prebuilt`].
73///
74/// # Arguments
75///
76/// The sections below provide an exhaustive list of all the arguments and flags supported by the [`prebuilt`][macro@prebuilt] macro:
77///
78/// | Name | Kind | Required |
79/// |-----------------------------------------------|----------|----------|
80/// | [`id`](#id) | Argument | No |
81/// | [`clone_if_necessary`](#clone_if_necessary) | Flag | No |
82/// | [`never_clone`](#never_clone) | Flag | No |
83/// | [`allow`](#allow) | Argument | No |
84///
85/// ## `id`
86///
87/// When using [`Blueprint::prebuilt`], Pavex generates a constant named after your type
88/// (converted to UPPER_SNAKE_CASE) that you use to refer to the prebuilt type.
89///
90/// The `id` argument allows you to customize the name of the generated constant.
91///
92/// ### Example
93///
94/// ```rust
95/// use pavex::{prebuilt, Blueprint};
96///
97/// #[prebuilt(id = "DB_POOL")]
98/// // 👆 Custom identifier
99/// #[derive(Debug)]
100/// pub struct DatabaseConnectionPool {
101/// // [...]
102/// }
103///
104/// # fn main() {
105/// let mut bp = Blueprint::new();
106/// // Use the custom identifier when registering
107/// bp.prebuilt(DB_POOL);
108/// # }
109/// ```
110///
111/// ## `clone_if_necessary`
112///
113/// By default, Pavex will **not** clone prebuilt types. The `clone_if_necessary` flag
114/// allows Pavex to invoke `.clone()` on the type if it helps satisfy Rust's borrow checker.
115///
116/// The prebuilt type must implement the `Clone` trait.
117///
118/// This flag is mutually exclusive with `never_clone`.
119///
120/// ### Example
121///
122/// ```rust
123/// use pavex::prebuilt;
124///
125/// #[prebuilt(clone_if_necessary)]
126/// // 👆 Allow cloning when needed
127/// #[derive(Debug, Clone)]
128/// pub struct DatabaseConnectionPool {
129/// // [...]
130/// }
131/// ```
132///
133/// ## `never_clone`
134///
135/// The `never_clone` flag explicitly prevents Pavex from cloning the prebuilt type.
136/// This is the default behavior for prebuilt types, so this flag is typically used
137/// for clarity and explicitness.
138///
139/// This flag is mutually exclusive with `clone_if_necessary`.
140///
141/// ### Example
142///
143/// ```rust
144/// use pavex::prebuilt;
145///
146/// #[prebuilt(never_clone)]
147/// // 👆 Explicitly prevent cloning (default behavior)
148/// #[derive(Debug)]
149/// pub struct NonCloneableResource {
150/// // Some resource that shouldn't be cloned
151/// file_handle: std::fs::File,
152/// }
153/// ```
154///
155/// Pavex will report an error during the code-generation phase if cloning is required
156/// but forbidden.
157///
158/// ## `allow`
159///
160/// The `allow` argument can be used to suppress specific warnings.
161///
162/// Currently, only one value is supported:
163/// - `unused`: Suppress warnings if this prebuilt type is registered but never used
164///
165/// ### Example
166///
167/// ```rust
168/// use pavex::prebuilt;
169///
170/// #[prebuilt(allow(unused))]
171/// // 👆 Don't warn if unused
172/// #[derive(Debug, Clone)]
173/// pub struct DatabaseConnectionPool {
174/// // [...]
175/// }
176/// ```
177///
178/// [`Blueprint::import`]: crate::Blueprint::import
179/// [`Blueprint::prebuilt`]: crate::Blueprint::prebuilt
180pub use pavex_macros::prebuilt;
181
182/// Define a [configuration type](https://pavex.dev/docs/guide/configuration/).
183///
184/// # Example
185///
186/// ```rust
187/// use pavex::config;
188///
189/// #[config(key = "pool")]
190/// #[derive(serde::Deserialize, Debug, Clone)]
191/// pub struct PoolConfig {
192/// pub max_n_connections: u32,
193/// pub min_n_connections: u32,
194/// }
195/// ```
196///
197/// # Guide
198///
199/// Check out the ["Configuration"](https://pavex.dev/docs/guide/configuration/)
200/// section of Pavex's guide for a thorough introduction to configuration
201/// in Pavex applications.
202///
203/// # Import
204///
205/// Use [`Blueprint::config`] or [`Blueprint::import`] to add the newly-defined configuration type
206/// to your application.
207///
208/// # Arguments
209///
210/// The sections below provide an exhaustive list of all the arguments and flags supported by the [`config`][macro@config] macro:
211///
212/// | Name | Kind | Required |
213/// |---------------------------------------------|----------|----------|
214/// | [`key`](#key) | Argument | Yes |
215/// | [`default_if_missing`](#default_if_missing) | Flag | No |
216/// | [`include_if_unused`](#include_if_unused) | Flag | No |
217/// | [`never_clone`](#never_clone) | Flag | No |
218///
219/// ## `key`
220///
221/// The `config` macro expects a `key` argument.\
222/// `key` will be used as the name of the corresponding field in the
223/// [generated `ApplicationConfig` struct][`ApplicationConfig`].
224///
225/// The provided key must satisfy a few constraints:
226///
227/// - It can't be empty.
228/// - It must start with a letter.
229/// - It can only contain letters, numbers, and underscores.
230/// - It must be unique within the application.
231///
232/// ### Example
233///
234/// ```rust
235/// use pavex::config;
236///
237/// #[config(key = "pool")]
238/// // 👆 The key for this configuration type.
239/// #[derive(serde::Deserialize, Debug, Clone)]
240/// pub struct PoolConfig {
241/// pub max_n_connections: u32,
242/// pub min_n_connections: u32,
243/// }
244/// ```
245///
246/// ## `default_if_missing`
247///
248/// By default, Pavex considers all configuration types to be **required**.
249/// There **must** be a value for each configuration key in the source we're reading from—e.g. a
250/// YAML configuration file. If a key is missing, Pavex will return an error.
251///
252/// The `default_if_missing` flag disables this behaviour.
253/// Pavex will invoke [`Default::default()`][`std::default::Default::default`] to provide a default
254/// value if the configuration key was omitted by the configuration source. No error will be raised.
255///
256/// `default_if_missing` can only be used on types that implement the [`Default`] trait.
257///
258/// ### Example
259///
260/// Consider the following configuration type:
261///
262/// ```rust
263/// use pavex::config;
264///
265/// #[config(key = "pool", default_if_missing)]
266/// // 👆 The flag
267/// #[derive(serde::Deserialize, Debug, Clone)]
268/// pub struct PoolConfig {
269/// pub max_n_connections: u32,
270/// pub min_n_connections: u32,
271/// }
272///
273/// impl Default for PoolConfig {
274/// fn default() -> Self {
275/// Self {
276/// max_n_connections: 10,
277/// min_n_connections: 2,
278/// }
279/// }
280/// }
281/// ```
282///
283/// The definition of `ApplicationConfig`, in the generated server SDK code, will look like this:
284///
285/// ```rust
286/// # #[derive(Debug, Clone, Default, serde::Deserialize)]
287/// # struct PoolConfig {}
288/// #[derive(serde::Deserialize, Debug, Clone)]
289/// pub struct ApplicationConfig {
290/// #[serde(default)]
291/// // 👆 Tell `serde` to use the default value
292/// // if the field is missing.
293/// pub pool: PoolConfig,
294/// // [..other config types..]
295/// }
296/// ```
297///
298///
299/// Therefore, given this YAML configuration file as input,
300///
301/// ```yaml
302/// tls:
303/// enabled: true
304/// # No `pool` entry!
305/// ```
306///
307/// Pavex will initialize `PoolConfig` using its default values, rather than returning an error.
308///
309/// ## `include_if_unused`
310///
311/// By default, Pavex will prune unused configuration types from the
312/// final [`ApplicationConfig` type][`ApplicationConfig`].
313///
314/// The `include_if_unused` flag disables this behaviour.
315/// There will always be an entry in [`ApplicationConfig`] for configuration types
316/// marked as `include_if_unused`, even if their value is never accessed by any constructor,
317/// route, or middleware.
318///
319/// ### Example
320///
321/// Consider this configuration type:
322///
323/// ```rust
324/// use pavex::config;
325///
326/// #[config(key = "pool", include_if_unused)]
327/// // 👆 The flag
328/// #[derive(serde::Deserialize, Debug, Clone)]
329/// pub struct PoolConfig {
330/// pub max_n_connections: u32,
331/// pub min_n_connections: u32,
332/// }
333/// ```
334///
335/// The resulting `ApplicationConfig` will *always* contain an entry for `PoolConfig`,
336/// even if it's never used. In the generated server SDK code:
337///
338/// ```rust
339/// # #[derive(Debug, Clone, serde::Deserialize)]
340/// # struct PoolConfig {}
341/// #[derive(Debug, Clone, serde::Deserialize)]
342/// pub struct ApplicationConfig {
343/// pub pool: PoolConfig,
344/// // 👆 You'll always find this field.
345///
346/// // [..other config types..]
347/// }
348/// ```
349///
350/// ## `never_clone`
351///
352/// By default, Pavex will invoke `.clone()` on configuration types if it helps to satisfy
353/// Rust's borrow checker.
354///
355/// The `never_clone` flag disables this behaviour:
356///
357/// ```rust
358/// use pavex::config;
359///
360/// #[config(key = "pool", never_clone)]
361/// // 👆 The flag
362/// #[derive(serde::Deserialize, Debug)]
363/// pub struct PoolConfig {
364/// pub max_n_connections: u32,
365/// pub min_n_connections: u32,
366/// }
367/// ```
368///
369/// Pavex will report an error during the code-generation phase if cloning is required
370/// but forbidden.
371///
372/// [`Blueprint::import`]: crate::Blueprint::import
373/// [`Blueprint::config`]: crate::Blueprint::config
374/// [`ApplicationConfig`]: https://pavex.dev/docs/guide/configuration/application_config/
375pub use pavex_macros::config;
376
377/// Define a [request-scoped constructor](https://pavex.dev/docs/guide/dependency_injection/constructors/).
378///
379/// Request-scoped constructors are invoked once per request to create a new instance
380/// of their output type. The created instance is cached for the duration of the request
381/// processing lifecycle.
382///
383/// Check out [`#[singleton]`](macro@crate::singleton) and [`#[transient]`](macro@crate::transient)
384/// if you need to define constructors with different lifecycles.
385///
386/// # Example
387///
388/// ```rust
389/// use pavex::methods;
390///
391/// pub struct RequestId(uuid::Uuid);
392///
393/// #[methods]
394/// impl RequestId {
395/// #[request_scoped]
396/// pub fn new() -> Self {
397/// Self(uuid::Uuid::new_v4())
398/// }
399/// }
400/// ```
401///
402/// `RequestId::new` will be called once per request whenever a new instance of
403/// `RequestId` is needed.
404///
405/// # Guide
406///
407/// Check out the ["Dependency injection"](https://pavex.dev/docs/guide/dependency_injection)
408/// section of Pavex's guide for a thorough introduction to dependency injection
409/// in Pavex applications.
410///
411/// # Registration
412///
413/// You can register a request-scoped constructor with your application in two ways:
414/// - Use [`Blueprint::constructor`] to register a single constructor
415/// - Use [`Blueprint::import`] to import multiple constructors in bulk
416///
417/// The `#[request_scoped]` macro [generates a constant](#id) that you can use to refer to the
418/// constructor when invoking [`Blueprint::constructor`].
419///
420/// # Arguments
421///
422/// The sections below provide an exhaustive list of all the arguments and flags supported by the [`request_scoped`][macro@request_scoped] macro:
423///
424/// | Name | Kind | Required |
425/// |---------------------------------------------|----------|----------|
426/// | [`id`](#id) | Argument | No |
427/// | [`clone_if_necessary`](#clone_if_necessary) | Flag | No |
428/// | [`never_clone`](#never_clone) | Flag | No |
429/// | [`allow`](#allow) | Argument | No |
430///
431/// ## `id`
432///
433/// By default, Pavex generates a constant named after your type and method
434/// (converted to UPPER_SNAKE_CASE) that you use when registering the constructor.
435///
436/// The `id` argument allows you to customize the name of the generated constant.
437///
438/// ### Example
439///
440/// Using the default generated identifier:
441///
442/// ```rust
443/// use pavex::{methods, Blueprint};
444///
445/// pub struct RequestLogger {
446/// // [...]
447/// }
448///
449/// #[methods]
450/// impl RequestLogger {
451/// #[request_scoped]
452/// pub fn new() -> Self {
453/// Self {
454/// // [...]
455/// }
456/// }
457/// }
458///
459/// # fn main() {
460/// let mut bp = Blueprint::new();
461/// // The generated constant is named `REQUEST_LOGGER_NEW`
462/// bp.constructor(REQUEST_LOGGER_NEW);
463/// # }
464/// ```
465///
466/// Using a custom identifier:
467///
468/// ```rust
469/// use pavex::{methods, Blueprint};
470///
471/// pub struct RequestLogger {
472/// // [...]
473/// }
474///
475/// #[methods]
476/// impl RequestLogger {
477/// #[request_scoped(id = "LOGGER_CONSTRUCTOR")]
478/// // 👆 Custom identifier
479/// pub fn new() -> Self {
480/// Self {
481/// // [...]
482/// }
483/// }
484/// }
485///
486/// # fn main() {
487/// let mut bp = Blueprint::new();
488/// // Use the custom identifier when registering
489/// bp.constructor(LOGGER_CONSTRUCTOR);
490/// # }
491/// ```
492///
493/// ## `clone_if_necessary`
494///
495/// By default, Pavex will **not** clone the output of request-scoped constructors. The `clone_if_necessary`
496/// flag allows Pavex to invoke `.clone()` on the output if it helps satisfy Rust's borrow checker.
497///
498/// The constructed type must implement the `Clone` trait.
499///
500/// This flag is mutually exclusive with `never_clone`.
501///
502/// ### Example
503///
504/// ```rust
505/// use pavex::methods;
506/// use std::collections::HashMap;
507///
508/// #[derive(Clone)]
509/// pub struct RequestConfig {
510/// settings: HashMap<String, String>,
511/// }
512///
513/// #[methods]
514/// impl RequestConfig {
515/// #[request_scoped(clone_if_necessary)]
516/// // 👆 Allow cloning when needed
517/// pub fn new() -> Self {
518/// Self {
519/// settings: HashMap::new(),
520/// }
521/// }
522/// }
523/// ```
524///
525/// ## `never_clone`
526///
527/// The `never_clone` flag explicitly prevents Pavex from cloning the output of this constructor.
528/// This is the default behavior for request-scoped constructors, so this flag is typically used
529/// for clarity and explicitness.
530///
531/// This flag is mutually exclusive with `clone_if_necessary`.
532///
533/// ### Example
534///
535/// ```rust
536/// use pavex::methods;
537///
538/// pub struct ScratchPad {
539/// // Contains non-cloneable resources
540/// temp_file: std::fs::File,
541/// }
542///
543/// #[methods]
544/// impl ScratchPad {
545/// #[request_scoped(never_clone)]
546/// // 👆 Explicitly prevent cloning (default behavior)
547/// pub fn new() -> std::io::Result<Self> {
548/// Ok(Self {
549/// temp_file: std::fs::File::create("request.tmp")?,
550/// })
551/// }
552/// }
553/// ```
554///
555/// Pavex will report an error during the code-generation phase if cloning is required
556/// but forbidden.
557///
558/// ## `allow`
559///
560/// The `allow` argument can be used to suppress specific warnings.
561///
562/// Currently, only one value is supported:
563/// - `unused`: Suppress warnings if this constructor is registered but never used
564///
565/// ### Example
566///
567/// ```rust
568/// use pavex::methods;
569///
570/// pub struct DebugInfo {
571/// // [...]
572/// }
573///
574/// #[methods]
575/// impl DebugInfo {
576/// #[request_scoped(allow(unused))]
577/// // 👆 Don't warn if unused
578/// pub fn new() -> Self {
579/// Self {
580/// // [...]
581/// }
582/// }
583/// }
584/// ```
585///
586/// [`Blueprint::import`]: crate::Blueprint::import
587/// [`Blueprint::constructor`]: crate::Blueprint::constructor
588#[doc(alias = "constructor")]
589pub use pavex_macros::request_scoped;
590
591/// Define a [singleton constructor](https://pavex.dev/docs/guide/dependency_injection/constructors/).
592///
593/// Singleton constructors are invoked once (when the application starts up) to create
594/// a new instance of their output type. The created instance is then shared across all
595/// requests for the lifetime of the application.
596///
597/// Check out [`#[request_scoped]`](macro@crate::request_scoped) and [`#[transient]`](macro@crate::transient)
598/// if you need to define constructors with different lifecycles.
599///
600/// # Example
601///
602/// ```rust
603/// use pavex::methods;
604///
605/// pub struct DatabasePool {
606/// // [...]
607/// }
608///
609/// #[methods]
610/// impl DatabasePool {
611/// #[singleton]
612/// pub fn new() -> Self {
613/// Self {
614/// // [...]
615/// }
616/// }
617/// }
618/// ```
619///
620/// `DatabasePool::new` will be called once at application startup, and the resulting
621/// instance will be shared across all requests.
622///
623/// # Guide
624///
625/// Check out the ["Dependency injection"](https://pavex.dev/docs/guide/dependency_injection)
626/// section of Pavex's guide for a thorough introduction to dependency injection
627/// in Pavex applications.
628///
629/// # Registration
630///
631/// You can register a singleton constructor with your application in two ways:
632/// - Use [`Blueprint::constructor`] to register a single constructor
633/// - Use [`Blueprint::import`] to import multiple constructors in bulk
634///
635/// The `#[singleton]` macro [generates a constant](#id) that you can use to refer to the
636/// constructor when invoking [`Blueprint::constructor`].
637///
638/// # Arguments
639///
640/// The sections below provide an exhaustive list of all the arguments and flags supported by the [`singleton`][macro@singleton] macro:
641///
642/// | Name | Kind | Required |
643/// |---------------------------------------------|----------|----------|
644/// | [`id`](#id) | Argument | No |
645/// | [`clone_if_necessary`](#clone_if_necessary) | Flag | No |
646/// | [`never_clone`](#never_clone) | Flag | No |
647/// | [`allow`](#allow) | Argument | No |
648///
649/// ## `id`
650///
651/// By default, Pavex generates a constant named after your type and method
652/// (converted to UPPER_SNAKE_CASE) that you use when registering the constructor.
653///
654/// The `id` argument allows you to customize the name of the generated constant.
655///
656/// ### Example
657///
658/// Using the default generated identifier:
659///
660/// ```rust
661/// use pavex::{methods, Blueprint};
662///
663/// pub struct CacheManager {
664/// // [...]
665/// }
666///
667/// #[methods]
668/// impl CacheManager {
669/// #[singleton]
670/// pub fn new() -> Self {
671/// Self {
672/// // [...]
673/// }
674/// }
675/// }
676///
677/// # fn main() {
678/// let mut bp = Blueprint::new();
679/// // The generated constant is named `CACHE_MANAGER_NEW`
680/// bp.constructor(CACHE_MANAGER_NEW);
681/// # }
682/// ```
683///
684/// Using a custom identifier:
685///
686/// ```rust
687/// use pavex::{methods, Blueprint};
688///
689/// pub struct CacheManager {
690/// // [...]
691/// }
692///
693/// #[methods]
694/// impl CacheManager {
695/// #[singleton(id = "CACHE_CONSTRUCTOR")]
696/// // 👆 Custom identifier
697/// pub fn new() -> Self {
698/// Self {
699/// // [...]
700/// }
701/// }
702/// }
703///
704/// # fn main() {
705/// let mut bp = Blueprint::new();
706/// // Use the custom identifier when registering
707/// bp.constructor(CACHE_CONSTRUCTOR);
708/// # }
709/// ```
710///
711/// ## `clone_if_necessary`
712///
713/// By default, Pavex will **not** clone the output of singleton constructors. The `clone_if_necessary`
714/// flag allows Pavex to invoke `.clone()` on the output if it helps satisfy Rust's borrow checker.
715///
716/// The constructed type must implement the `Clone` trait.
717///
718/// This flag is mutually exclusive with `never_clone`.
719///
720/// ### Example
721///
722/// ```rust
723/// use pavex::methods;
724/// use std::collections::HashMap;
725///
726/// #[derive(Clone)]
727/// pub struct GlobalConfig {
728/// settings: HashMap<String, String>,
729/// }
730///
731/// #[methods]
732/// impl GlobalConfig {
733/// #[singleton(clone_if_necessary)]
734/// // 👆 Allow cloning when needed
735/// pub fn new() -> Self {
736/// Self {
737/// settings: HashMap::new(),
738/// }
739/// }
740/// }
741/// ```
742///
743/// ## `never_clone`
744///
745/// The `never_clone` flag explicitly prevents Pavex from cloning the output of this constructor.
746/// This is the default behavior for singleton constructors, so this flag is typically used
747/// for clarity and explicitness.
748///
749/// This flag is mutually exclusive with `clone_if_necessary`.
750///
751/// ### Example
752///
753/// ```rust
754/// use pavex::methods;
755///
756/// pub struct LogSink {
757/// // Contains non-cloneable resources
758/// handle: std::fs::File,
759/// }
760///
761/// #[methods]
762/// impl LogSink {
763/// #[singleton(never_clone)]
764/// // 👆 Explicitly prevent cloning (default behavior)
765/// pub fn new() -> std::io::Result<Self> {
766/// Ok(Self {
767/// handle: std::fs::File::create("global.log")?,
768/// })
769/// }
770/// }
771/// ```
772///
773/// Pavex will report an error during the code-generation phase if cloning is required
774/// but forbidden.
775///
776/// ## `allow`
777///
778/// The `allow` argument can be used to suppress specific warnings.
779///
780/// Currently, only one value is supported:
781/// - `unused`: Suppress warnings if this constructor is registered but never used
782///
783/// ### Example
784///
785/// ```rust
786/// use pavex::methods;
787///
788/// pub struct MetricsCollector {
789/// // [...]
790/// }
791///
792/// #[methods]
793/// impl MetricsCollector {
794/// #[singleton(allow(unused))]
795/// // 👆 Don't warn if unused
796/// pub fn new() -> Self {
797/// Self {
798/// // [...]
799/// }
800/// }
801/// }
802/// ```
803///
804/// [`Blueprint::import`]: crate::Blueprint::import
805/// [`Blueprint::constructor`]: crate::Blueprint::constructor
806#[doc(alias = "constructor")]
807pub use pavex_macros::singleton;
808
809/// Define a [transient constructor](https://pavex.dev/docs/guide/dependency_injection/constructors/).
810///
811/// Transient constructors are invoked each time a new instance of their output type
812/// is needed, even within the same request. The created instances are not cached.
813///
814/// Check out [`#[singleton]`](macro@crate::singleton) and [`#[request_scoped]`](macro@crate::request_scoped)
815/// if you need to define constructors with different lifecycles.
816///
817/// # Example
818///
819/// ```rust
820/// use pavex::methods;
821///
822/// pub struct TemporaryBuffer {
823/// data: Vec<u8>,
824/// }
825///
826/// #[methods]
827/// impl TemporaryBuffer {
828/// #[transient]
829/// pub fn new() -> Self {
830/// Self {
831/// data: Vec::with_capacity(1024),
832/// }
833/// }
834/// }
835/// ```
836///
837/// `TemporaryBuffer::new` will be called each time a new instance of `TemporaryBuffer` is needed,
838/// even within the same request.
839///
840/// # Guide
841///
842/// Check out the ["Dependency injection"](https://pavex.dev/docs/guide/dependency_injection)
843/// section of Pavex's guide for a thorough introduction to dependency injection
844/// in Pavex applications.
845///
846/// # Registration
847///
848/// You can register a transient constructor with your application in two ways:
849/// - Use [`Blueprint::constructor`] to register a single constructor
850/// - Use [`Blueprint::import`] to import multiple constructors in bulk
851///
852/// The `#[transient]` macro [generates a constant](#id) that you can use to refer to the
853/// constructor when invoking [`Blueprint::constructor`].
854///
855/// # Arguments
856///
857/// The sections below provide an exhaustive list of all the arguments and flags supported by the [`transient`][macro@transient] macro:
858///
859/// | Name | Kind | Required |
860/// |---------------------------------------------|----------|----------|
861/// | [`id`](#id) | Argument | No |
862/// | [`clone_if_necessary`](#clone_if_necessary) | Flag | No |
863/// | [`never_clone`](#never_clone) | Flag | No |
864/// | [`allow`](#allow) | Argument | No |
865///
866/// ## `id`
867///
868/// By default, Pavex generates a constant named after your type and method
869/// (converted to UPPER_SNAKE_CASE) that you use when registering the constructor.
870///
871/// The `id` argument allows you to customize the name of the generated constant.
872///
873/// ### Example
874///
875/// Using the default generated identifier:
876///
877/// ```rust
878/// use pavex::{methods, Blueprint};
879///
880/// pub struct TokenGenerator {
881/// // [...]
882/// }
883///
884/// #[methods]
885/// impl TokenGenerator {
886/// #[transient]
887/// pub fn new() -> Self {
888/// Self {
889/// // [...]
890/// }
891/// }
892/// }
893///
894/// # fn main() {
895/// let mut bp = Blueprint::new();
896/// // The generated constant is named `TOKEN_GENERATOR_NEW`
897/// bp.constructor(TOKEN_GENERATOR_NEW);
898/// # }
899/// ```
900///
901/// Using a custom identifier:
902///
903/// ```rust
904/// use pavex::{methods, Blueprint};
905///
906/// pub struct TokenGenerator {
907/// // [...]
908/// }
909///
910/// #[methods]
911/// impl TokenGenerator {
912/// #[transient(id = "TOKEN_CONSTRUCTOR")]
913/// // 👆 Custom identifier
914/// pub fn new() -> Self {
915/// Self {
916/// // [...]
917/// }
918/// }
919/// }
920///
921/// # fn main() {
922/// let mut bp = Blueprint::new();
923/// // Use the custom identifier when registering
924/// bp.constructor(TOKEN_CONSTRUCTOR);
925/// # }
926/// ```
927///
928/// ## `clone_if_necessary`
929///
930/// By default, Pavex will **not** clone the output of transient constructors. The `clone_if_necessary`
931/// flag allows Pavex to invoke `.clone()` on the output if it helps satisfy Rust's borrow checker.
932///
933/// The constructed type must implement the `Clone` trait.
934///
935/// This flag is mutually exclusive with `never_clone`.
936///
937/// ### Example
938///
939/// ```rust
940/// use pavex::{transient, methods};
941/// use uuid::Uuid;
942///
943/// #[derive(Clone)]
944/// pub struct InstanceId {
945/// value: Uuid,
946/// }
947///
948/// #[methods]
949/// impl InstanceId {
950/// #[transient(clone_if_necessary)]
951/// // 👆 Allow cloning when needed
952/// pub fn new() -> Self {
953/// Self {
954/// value: uuid::Uuid::new_v4(),
955/// }
956/// }
957/// }
958/// ```
959///
960/// ## `never_clone`
961///
962/// The `never_clone` flag explicitly prevents Pavex from cloning the output of this constructor.
963/// This is the default behavior for transient constructors, so this flag is typically used
964/// for clarity and explicitness.
965///
966/// This flag is mutually exclusive with `clone_if_necessary`.
967///
968/// ### Example
969///
970/// ```rust
971/// use pavex::methods;
972///
973/// pub struct TempFile {
974/// // Contains non-cloneable resources
975/// handle: std::fs::File,
976/// }
977///
978/// #[methods]
979/// impl TempFile {
980/// #[transient(never_clone)]
981/// // 👆 Explicitly prevent cloning (default behavior)
982/// pub fn new() -> std::io::Result<Self> {
983/// Ok(Self {
984/// handle: std::fs::File::create_new("temp.tmp")?,
985/// })
986/// }
987/// }
988/// ```
989///
990/// Pavex will report an error during the code-generation phase if cloning is required
991/// but forbidden.
992///
993/// ## `allow`
994///
995/// The `allow` argument can be used to suppress specific warnings.
996///
997/// Currently, only one value is supported:
998/// - `unused`: Suppress warnings if this constructor is registered but never used
999///
1000/// ### Example
1001///
1002/// ```rust
1003/// use pavex::methods;
1004///
1005/// pub struct TraceId {
1006/// // [...]
1007/// }
1008///
1009/// #[methods]
1010/// impl TraceId {
1011/// #[transient(allow(unused))]
1012/// // 👆 Don't warn if unused
1013/// pub fn new() -> Self {
1014/// Self {
1015/// // [...]
1016/// }
1017/// }
1018/// }
1019/// ```
1020///
1021/// [`Blueprint::import`]: crate::Blueprint::import
1022/// [`Blueprint::constructor`]: crate::Blueprint::constructor
1023#[doc(alias = "constructor")]
1024pub use pavex_macros::transient;
1025
1026/// Define a [wrapping middleware](https://pavex.dev/docs/guide/middleware/wrapping/).
1027///
1028/// # Example
1029///
1030/// A middleware that applies a timeout to all incoming requests:
1031///
1032/// ```rust
1033/// use pavex::{wrap, middleware::Next, Response};
1034/// use tokio::time::error::Elapsed;
1035///
1036/// #[wrap]
1037/// pub async fn timeout<C>(next: Next<C>) -> Result<Response, Elapsed>
1038/// where
1039/// C: IntoFuture<Output = Response>,
1040/// {
1041/// let max_duration = std::time::Duration::from_secs(20);
1042/// tokio::time::timeout(max_duration, next.into_future()).await
1043/// }
1044/// ```
1045///
1046/// # Guide
1047///
1048/// Check out the ["Middlewares"](https://pavex.dev/docs/guide/middleware/)
1049/// section of Pavex's guide for a thorough introduction to middlewares
1050/// in Pavex applications.
1051///
1052/// # Registration
1053///
1054/// Use [`Blueprint::wrap`] to register the middleware with your [`Blueprint`].
1055///
1056/// The `#[wrap]` macro [generates a constant](#id) that you can use to refer to the
1057/// middleware when invoking [`Blueprint::wrap`].
1058///
1059/// # Arguments
1060///
1061/// The sections below provide an exhaustive list of all the arguments and flags supported by the [`wrap`][macro@wrap] macro:
1062///
1063/// | Name | Kind | Required |
1064/// |---------------------|----------|----------|
1065/// | [`id`](#id) | Argument | No |
1066///
1067/// ## `id`
1068///
1069/// By default, Pavex generates a constant named after your function
1070/// (converted to UPPER_SNAKE_CASE) that you use when registering the middleware.
1071///
1072/// The `id` argument allows you to customize the name of the generated constant.
1073///
1074/// ### Example
1075///
1076/// Using the default generated identifier:
1077///
1078/// ```rust
1079/// use pavex::{wrap, Blueprint, middleware::Next, Response};
1080/// use tokio::time::error::Elapsed;
1081///
1082/// #[wrap]
1083/// pub async fn timeout<C>(next: Next<C>) -> Result<Response, Elapsed>
1084/// where
1085/// C: IntoFuture<Output = Response>,
1086/// {
1087/// let max_duration = std::time::Duration::from_secs(20);
1088/// tokio::time::timeout(max_duration, next.into_future()).await
1089/// }
1090///
1091/// # fn main() {
1092/// let mut bp = Blueprint::new();
1093/// bp.wrap(TIMEOUT);
1094/// # }
1095/// ```
1096///
1097/// Using a custom identifier:
1098///
1099/// ```rust
1100/// use pavex::{wrap, Blueprint, middleware::Next, Response};
1101/// use tokio::time::error::Elapsed;
1102///
1103/// #[wrap(id = "MY_TIMEOUT")]
1104/// // 👆 Custom identifier
1105/// pub async fn timeout<C>(next: Next<C>) -> Result<Response, Elapsed>
1106/// where
1107/// C: IntoFuture<Output = Response>,
1108/// {
1109/// let max_duration = std::time::Duration::from_secs(20);
1110/// tokio::time::timeout(max_duration, next.into_future()).await
1111/// }
1112///
1113/// # fn main() {
1114/// let mut bp = Blueprint::new();
1115/// // Use the custom identifier when registering
1116/// bp.wrap(MY_TIMEOUT);
1117/// # }
1118/// ```
1119///
1120/// [`Blueprint::wrap`]: crate::Blueprint::wrap
1121/// [`Blueprint`]: crate::Blueprint
1122#[doc(alias = "middleware")]
1123pub use pavex_macros::wrap;
1124
1125/// Define a [pre-processing middleware](https://pavex.dev/docs/guide/middleware/pre_processing/).
1126///
1127/// # Example
1128///
1129/// Redirect requests to paths that end with a trailing `/` to
1130/// the equivalent path without the trailing `/`:
1131///
1132/// ```rust
1133/// use pavex::{pre_process, http::{HeaderValue, header::LOCATION}};
1134/// use pavex::middleware::Processing;
1135/// use pavex::request::RequestHead;
1136/// use pavex::Response;
1137///
1138/// #[pre_process]
1139/// pub fn redirect_to_normalized(head: &RequestHead) -> Processing {
1140/// let Some(normalized_path) = head.target.path().strip_suffix('/') else {
1141/// // No need to redirect, we continue processing the request.
1142/// return Processing::Continue;
1143/// };
1144/// let location = HeaderValue::from_str(normalized_path).unwrap();
1145/// let redirect = Response::temporary_redirect().insert_header(LOCATION, location);
1146/// // Short-circuit the request processing pipeline and return a redirect response
1147/// Processing::EarlyReturn(redirect)
1148/// }
1149/// ```
1150///
1151/// # Guide
1152///
1153/// Check out the ["Middlewares"](https://pavex.dev/docs/guide/middleware/)
1154/// section of Pavex's guide for a thorough introduction to middlewares
1155/// in Pavex applications.
1156///
1157/// # Registration
1158///
1159/// Use [`Blueprint::pre_process`] to register the middleware with your [`Blueprint`].
1160///
1161/// The `#[pre_process]` macro [generates a constant](#id) that you can use to refer to the
1162/// middleware when invoking [`Blueprint::pre_process`].
1163///
1164/// # Arguments
1165///
1166/// The sections below provide an exhaustive list of all the arguments and flags supported by the [`pre_process`][macro@pre_process] macro:
1167///
1168/// | Name | Kind | Required |
1169/// |---------------------|----------|----------|
1170/// | [`id`](#id) | Argument | No |
1171///
1172/// ## `id`
1173///
1174/// By default, Pavex generates a constant named after your function
1175/// (converted to UPPER_SNAKE_CASE) that you use when registering the middleware.
1176///
1177/// The `id` argument allows you to customize the name of the generated constant.
1178///
1179/// ### Example
1180///
1181/// Using the default generated identifier:
1182///
1183/// ```rust
1184/// use pavex::{pre_process, Blueprint, middleware::Processing};
1185///
1186/// #[pre_process]
1187/// pub fn redirect_to_normalized() -> Processing {
1188/// Processing::Continue
1189/// }
1190///
1191/// # fn main() {
1192/// let mut bp = Blueprint::new();
1193/// bp.pre_process(REDIRECT_TO_NORMALIZED);
1194/// # }
1195/// ```
1196///
1197/// Using a custom identifier:
1198///
1199/// ```rust
1200/// use pavex::{pre_process, Blueprint, middleware::Processing, request::RequestHead};
1201///
1202/// #[pre_process(id = "TO_NORMALIZED")]
1203/// // 👆 Custom identifier
1204/// pub fn redirect_to_normalized(head: &RequestHead) -> Processing {
1205/// // [...]
1206/// Processing::Continue
1207/// }
1208///
1209/// # fn main() {
1210/// let mut bp = Blueprint::new();
1211/// // Use the custom identifier when registering
1212/// bp.pre_process(TO_NORMALIZED);
1213/// # }
1214/// ```
1215///
1216/// [`Blueprint::pre_process`]: crate::Blueprint::pre_process
1217/// [`Blueprint`]: crate::Blueprint
1218#[doc(alias = "middleware")]
1219pub use pavex_macros::pre_process;
1220
1221/// Define a [post-processing middleware](https://pavex.dev/docs/guide/middleware/post_processing/).
1222///
1223/// # Example
1224///
1225/// Log the status code of the HTTP response returned to the caller:
1226///
1227/// ```rust
1228/// use pavex::{post_process, Response};
1229/// use pavex_tracing::{
1230/// RootSpan,
1231/// fields::{http_response_status_code, HTTP_RESPONSE_STATUS_CODE}
1232/// };
1233///
1234/// #[post_process]
1235/// pub fn response_logger(response: Response, root_span: &RootSpan) -> Response
1236/// {
1237/// root_span.record(
1238/// HTTP_RESPONSE_STATUS_CODE,
1239/// http_response_status_code(&response),
1240/// );
1241/// response
1242/// }
1243/// ```
1244///
1245/// # Guide
1246///
1247/// Check out the ["Middlewares"](https://pavex.dev/docs/guide/middleware/)
1248/// section of Pavex's guide for a thorough introduction to middlewares
1249/// in Pavex applications.
1250///
1251/// # Registration
1252///
1253/// Use [`Blueprint::post_process`] to register the middleware with your [`Blueprint`].
1254///
1255/// The `#[post_process]` macro [generates a constant](#id) that you can use to refer to the
1256/// middleware when invoking [`Blueprint::post_process`].
1257///
1258/// # Arguments
1259///
1260/// The sections below provide an exhaustive list of all the arguments and flags supported by the [`post_process`][macro@post_process] macro:
1261///
1262/// | Name | Kind | Required |
1263/// |---------------------|----------|----------|
1264/// | [`id`](#id) | Argument | No |
1265///
1266/// ## `id`
1267///
1268/// By default, Pavex generates a constant named after your function
1269/// (converted to UPPER_SNAKE_CASE) that you use when registering the middleware.
1270///
1271/// The `id` argument allows you to customize the name of the generated constant.
1272///
1273/// ### Example
1274///
1275/// Using the default generated identifier:
1276///
1277/// ```rust
1278/// use pavex::{post_process, Blueprint, Response};
1279/// use pavex_tracing::RootSpan;
1280///
1281/// #[post_process]
1282/// pub fn response_logger(response: Response, root_span: &RootSpan) -> Response
1283/// {
1284/// // [...]
1285/// # todo!()
1286/// }
1287///
1288/// # fn main() {
1289/// let mut bp = Blueprint::new();
1290/// // The generated constant is named `RESPONSE_LOGGER`
1291/// bp.post_process(RESPONSE_LOGGER);
1292/// # }
1293/// ```
1294///
1295/// Using a custom identifier:
1296///
1297/// ```rust
1298/// use pavex::{post_process, Blueprint, Response};
1299/// use pavex_tracing::RootSpan;
1300///
1301/// #[post_process(id = "LOG_RESPONSE")]
1302/// // 👆 Custom identifier
1303/// pub fn response_logger(response: Response, root_span: &RootSpan) -> Response
1304/// {
1305/// // [...]
1306/// # todo!()
1307/// }
1308///
1309/// # fn main() {
1310/// let mut bp = Blueprint::new();
1311/// // Use the custom identifier when registering
1312/// bp.post_process(LOG_RESPONSE);
1313/// # }
1314/// ```
1315///
1316/// [`Blueprint::post_process`]: crate::Blueprint::post_process
1317/// [`Blueprint`]: crate::Blueprint
1318#[doc(alias = "middleware")]
1319pub use pavex_macros::post_process;
1320
1321/// Define an [error handler](https://pavex.dev/docs/guide/errors/error_handlers/).
1322///
1323/// Error handlers are invoked whenever an error occurs during request processing,
1324/// allowing you to transform errors into HTTP responses.
1325///
1326/// # Example
1327///
1328/// ```rust
1329/// use pavex::error_handler;
1330/// use pavex::Response;
1331/// # struct AuthError;
1332///
1333/// #[error_handler]
1334/// pub fn handle_auth_error(e: &AuthError) -> Response {
1335/// // Transform the error into an HTTP response
1336/// Response::unauthorized()
1337/// }
1338/// ```
1339///
1340/// # Guide
1341///
1342/// Check out the [\"Error handling\"](https://pavex.dev/docs/guide/errors)
1343/// section of Pavex's guide for a thorough introduction to error handling
1344/// in Pavex applications.
1345///
1346/// # Registration
1347///
1348/// You can register an error handler with your application in two ways:
1349/// - Use [`Blueprint::error_handler`] to register a single error handler
1350/// - Use [`Blueprint::import`] to import multiple error handlers in bulk
1351///
1352/// The `#[error_handler]` macro [generates a constant](#id) that you can use to refer to the
1353/// error handler when invoking [`Blueprint::error_handler`].
1354///
1355/// # Arguments
1356///
1357/// The sections below provide an exhaustive list of all the arguments and helper attributes supported by the [`error_handler`][macro@error_handler] macro:
1358///
1359/// | Name | Kind | Required |
1360/// |-------------------------------|------------------|-----------|
1361/// | [`px(error_ref)`](#error_ref) | Helper attribute | Sometimes |
1362/// | [`id`](#id) | Argument | No |
1363/// | [`default`](#default) | Argument | No |
1364///
1365/// ## `error_ref`
1366///
1367/// One of the input parameters for an error handler must be a reference to the error type that's being handled.
1368///
1369/// Pavex infers the error type automatically if the error handler has a single input parameter.\
1370/// If there are multiple input parameters, you must annotate the error reference with `#[px(error_ref)]`.
1371///
1372/// ### Example: single input parameter
1373///
1374/// ```rust
1375/// use pavex::methods;
1376/// use pavex::Response;
1377///
1378/// pub struct AuthError { /* */ };
1379///
1380/// #[methods]
1381/// impl AuthError {
1382/// #[error_handler]
1383/// // A single input parameter, no need for additional annotations
1384/// // Pavex will infer that `&self` is the error reference
1385/// pub fn to_response(&self) -> Response {
1386/// // [...]
1387/// # Response::ok()
1388/// }
1389/// }
1390/// ```
1391///
1392/// ### Example: multiple input parameters
1393///
1394/// ```rust
1395/// use pavex::methods;
1396/// use pavex::Response;
1397///
1398/// pub struct AuthError { /* */ };
1399/// # pub struct OrgId;
1400///
1401/// #[methods]
1402/// impl AuthError {
1403/// #[error_handler]
1404/// pub fn to_response(
1405/// #[px(error_ref)] &self,
1406/// // 👆
1407/// // Multiple input parameters, you must mark the error reference
1408/// organization_id: OrgId
1409/// ) -> Response {
1410/// // [...]
1411/// # Response::ok()
1412/// }
1413/// }
1414/// ```
1415///
1416/// ## `id`
1417///
1418/// When using [`Blueprint::error_handler`], Pavex generates a constant named after your function
1419/// (converted to UPPER_SNAKE_CASE) that you can use to refer to the error handler
1420/// when invoking [`Blueprint::error_handler`].
1421///
1422/// The `id` argument allows you to customize the name of the generated constant.
1423///
1424/// ### Example
1425///
1426/// Using the default identifier:
1427///
1428/// ```rust
1429/// use pavex::{error_handler, Blueprint};
1430/// use pavex::Response;
1431/// # struct AuthError;
1432///
1433/// #[error_handler]
1434/// pub fn handle_auth_error(e: &AuthError) -> Response {
1435/// // [...]
1436/// # todo!()
1437/// }
1438///
1439/// let mut bp = Blueprint::new();
1440/// bp.error_handler(HANDLE_AUTH_ERROR);
1441/// ```
1442///
1443/// Using a custom identifier:
1444///
1445/// ```rust
1446/// use pavex::{error_handler, Blueprint};
1447/// use pavex::Response;
1448///
1449/// #[error_handler(id = "AUTH_HANDLER")]
1450/// // 👆 Custom identifier
1451/// pub fn handle_auth_error(e: &AuthError) -> Response {
1452/// // [...]
1453/// # todo!()
1454/// }
1455///
1456/// let mut bp = Blueprint::new();
1457/// bp.error_handler(AUTH_HANDLER);
1458/// # struct AuthError;
1459/// ```
1460///
1461/// ## `default`
1462///
1463/// The `default` argument determines whether this error handler should be used as the
1464/// default handler for the error type whenever an error of the matching type is emitted.
1465///
1466/// By default, error handlers are considered the default handler for their error type (`default = true`).
1467///
1468/// ### Example
1469///
1470/// ```rust
1471/// use pavex::{error_handler, get, Blueprint};
1472/// use pavex::Response;
1473///
1474/// #[error_handler]
1475/// // This is the default handler for `AuthError`s
1476/// pub fn handle_auth_error(e: &AuthError) -> Response {
1477/// # todo!()
1478/// }
1479///
1480/// #[error_handler(default = false)]
1481/// // 👆 Not the default handler
1482/// pub fn handle_auth_error_admin(e: &AuthError) -> Response {
1483/// # todo!()
1484/// }
1485///
1486/// #[get(path = "/admin")]
1487/// pub fn admin_route() -> Result<Response, AuthError> {
1488/// // Admin-specific logic
1489/// # todo!()
1490/// }
1491///
1492/// let mut bp = Blueprint::new();
1493/// // Register the default error handler
1494/// bp.error_handler(HANDLE_AUTH_ERROR);
1495/// // Specify a different error handler for the admin route
1496/// bp.route(ADMIN_ROUTE).error_handler(HANDLE_AUTH_ERROR_ADMIN);
1497/// # struct AuthError;
1498/// ```
1499pub use pavex_macros::error_handler;
1500
1501/// Define an [error observer](https://pavex.dev/docs/guide/errors/error_observers/).
1502///
1503/// Error observers are invoked whenever an error occurs during request processing,
1504/// allowing you to log errors, send them to monitoring services, or perform other
1505/// observability tasks.
1506///
1507/// # Example
1508///
1509/// Log errors that occur during request processing:
1510///
1511/// ```rust
1512/// use pavex::error_observer;
1513/// use tracing_log_error::log_error;
1514///
1515/// #[error_observer]
1516/// pub async fn error_logger(e: &pavex::Error) {
1517/// log_error!(e)
1518/// }
1519/// ```
1520///
1521/// # Guide
1522///
1523/// Check out the ["Errors"](https://pavex.dev/docs/guide/errors/)
1524/// section of Pavex's guide for a thorough introduction to errors
1525/// in Pavex applications.
1526///
1527/// # Registration
1528///
1529/// Use [`Blueprint::error_observer`] to register the error observer with your [`Blueprint`].
1530///
1531/// The `#[error_observer]` macro [generates a constant](#id) that you can use to refer to the
1532/// observer when invoking [`Blueprint::error_observer`].
1533///
1534/// # Arguments
1535///
1536/// The sections below provide an exhaustive list of all the arguments and flags supported by the [`error_observer`][macro@error_observer] macro:
1537///
1538/// | Name | Kind | Required |
1539/// |---------------------|----------|----------|
1540/// | [`id`](#id) | Argument | No |
1541///
1542/// ## `id`
1543///
1544/// By default, Pavex generates a constant named after your function
1545/// (converted to UPPER_SNAKE_CASE) that you use when registering the error observer.
1546///
1547/// The `id` argument allows you to customize the name of the generated constant.
1548///
1549/// ### Example
1550///
1551/// Using the default generated identifier:
1552///
1553/// ```rust
1554/// use pavex::{error_observer, Blueprint};
1555///
1556/// #[error_observer]
1557/// pub async fn error_logger(e: &pavex::Error) {
1558/// // Log the error
1559/// }
1560///
1561/// # fn main() {
1562/// let mut bp = Blueprint::new();
1563/// // The generated constant is named `ERROR_LOGGER`
1564/// bp.error_observer(ERROR_LOGGER);
1565/// # }
1566/// ```
1567///
1568/// Using a custom identifier:
1569///
1570/// ```rust
1571/// use pavex::{error_observer, Blueprint};
1572///
1573/// #[error_observer(id = "MY_ERROR_LOGGER")]
1574/// // 👆 Custom identifier
1575/// pub async fn error_logger(e: &pavex::Error) {
1576/// // Log the error
1577/// }
1578///
1579/// # fn main() {
1580/// let mut bp = Blueprint::new();
1581/// // Use the custom identifier when registering
1582/// bp.error_observer(MY_ERROR_LOGGER);
1583/// # }
1584/// ```
1585///
1586/// [`Blueprint::error_observer`]: crate::Blueprint::error_observer
1587/// [`Blueprint`]: crate::Blueprint
1588pub use pavex_macros::error_observer;
1589
1590macro_rules! http_method_macro_doc {
1591 ($method:literal, $macro_name:ident, $example_fn:ident, $constant_name:ident, $example_path:literal, $example_comment:literal) => {
1592 #[doc = concat!("Define a [route](https://pavex.dev/docs/guide/routing/) for ", $method, " requests to a given path.")]
1593 ///
1594 #[doc = concat!("This is a shorthand for [`#[route(method = \"", $method, "\", path = \"...\")]`](macro@route).")]
1595 ///
1596 /// # Example
1597 ///
1598 /// ```rust
1599 #[doc = concat!("use pavex::{", stringify!($macro_name), ", Response};")]
1600 ///
1601 #[doc = concat!("#[", stringify!($macro_name), "(path = \"", $example_path, "\")]")]
1602 #[doc = concat!("pub async fn ", stringify!($example_fn), "(/* */) -> Response {")]
1603 #[doc = concat!(" // ", $example_comment)]
1604 /// // [...]
1605 /// # Response::ok()
1606 /// }
1607 /// ```
1608 ///
1609 /// # Guide
1610 ///
1611 /// Check out the ["Routing"](https://pavex.dev/docs/guide/routing/)
1612 /// section of Pavex's guide for a thorough introduction to routing
1613 /// in Pavex applications.
1614 ///
1615 /// # Registration
1616 ///
1617 #[doc = concat!("You can register a ", $method, " route with your application in two ways:")]
1618 /// - Use [`Blueprint::route`] to register a single route
1619 /// - Use [`Blueprint::import`] to import multiple routes in bulk
1620 ///
1621 #[doc = concat!("The `#[", stringify!($macro_name), "]` macro [generates a constant](#id) that you can use to refer to the")]
1622 /// route when invoking [`Blueprint::route`].
1623 ///
1624 /// # Arguments
1625 ///
1626 #[doc = concat!("The sections below provide an exhaustive list of all the arguments supported by the [`", stringify!($macro_name), "`][macro@", stringify!($macro_name), "] macro:")]
1627 ///
1628 /// | Name | Kind | Required |
1629 /// |-----------------------------------|----------|----------|
1630 /// | [`path`](#path) | Argument | Yes |
1631 /// | [`id`](#id) | Argument | No |
1632 ///
1633 /// ## `path`
1634 ///
1635 /// The `path` argument specifies the URL path pattern that this route will match.
1636 ///
1637 /// The path can contain dynamic parameter placeholders in the format `{parameter_name}`.
1638 /// Check out the [guide on parameter extraction](https://pavex.dev/docs/guide/routing/path_patterns/#path-parameters)
1639 /// for a detailed explanation.
1640 ///
1641 /// ### Example
1642 ///
1643 /// ```rust
1644 #[doc = concat!("use pavex::{", stringify!($macro_name), ", Response};")]
1645 ///
1646 #[doc = concat!("#[", stringify!($macro_name), "(path = \"", $example_path, "\")]")]
1647 /// // 👆 Path with parameter
1648 #[doc = concat!("pub async fn ", stringify!($example_fn), "(/* */) -> Response {")]
1649 /// // [...]
1650 /// # Response::ok()
1651 /// }
1652 /// ```
1653 ///
1654 /// ## `id`
1655 ///
1656 /// By default, Pavex generates a constant named after your function
1657 /// (converted to UPPER_SNAKE_CASE) that you can use when invoking [`Blueprint::route`].
1658 ///
1659 /// The `id` argument allows you to customize the name of the generated constant.
1660 ///
1661 /// ### Example
1662 ///
1663 /// Using the default generated identifier:
1664 ///
1665 /// ```rust
1666 #[doc = concat!("use pavex::{", stringify!($macro_name), ", Response, Blueprint};")]
1667 ///
1668 #[doc = concat!("#[", stringify!($macro_name), "(path = \"", $example_path, "\")]")]
1669 #[doc = concat!("pub async fn ", stringify!($example_fn), "(/* */) -> Response {")]
1670 /// // [...]
1671 /// # Response::ok()
1672 /// }
1673 ///
1674 /// # fn main() {
1675 /// let mut bp = Blueprint::new();
1676 #[doc = concat!("// The generated constant is named `", stringify!($constant_name), "`")]
1677 #[doc = concat!("bp.route(", stringify!($constant_name), ");")]
1678 /// # }
1679 /// ```
1680 ///
1681 /// Using a custom identifier:
1682 ///
1683 /// ```rust
1684 #[doc = concat!("use pavex::{", stringify!($macro_name), ", Response, Blueprint};")]
1685 ///
1686 #[doc = concat!("#[", stringify!($macro_name), "(path = \"", $example_path, "\", id = \"CUSTOM_ROUTE\")]")]
1687 /// // 👆 Custom identifier
1688 #[doc = concat!("pub async fn ", stringify!($example_fn), "(id: u32) -> Response {")]
1689 /// // [...]
1690 /// # Response::ok()
1691 /// }
1692 ///
1693 /// # fn main() {
1694 /// let mut bp = Blueprint::new();
1695 /// // Use the custom identifier when registering
1696 /// bp.route(CUSTOM_ROUTE);
1697 /// # }
1698 /// ```
1699 ///
1700 /// [`Blueprint::import`]: crate::Blueprint::import
1701 /// [`Blueprint::route`]: crate::Blueprint::route
1702 #[doc(alias = "route")]
1703 #[doc(alias = "request_handler")]
1704 pub use pavex_macros::$macro_name;
1705 };
1706}
1707
1708http_method_macro_doc!(
1709 "DELETE",
1710 delete,
1711 delete_user,
1712 DELETE_USER,
1713 "/users/{id}",
1714 "Delete user logic"
1715);
1716http_method_macro_doc!(
1717 "GET",
1718 get,
1719 get_user,
1720 GET_USER,
1721 "/users/{id}",
1722 "Get user logic"
1723);
1724http_method_macro_doc!(
1725 "HEAD",
1726 head,
1727 head_user,
1728 HEAD_USER,
1729 "/users/{id}",
1730 "Head user logic"
1731);
1732http_method_macro_doc!(
1733 "OPTIONS",
1734 options,
1735 options_user,
1736 OPTIONS_USER,
1737 "/users/{id}",
1738 "Options user logic"
1739);
1740http_method_macro_doc!(
1741 "PATCH",
1742 patch,
1743 patch_user,
1744 PATCH_USER,
1745 "/users/{id}",
1746 "Patch user logic"
1747);
1748http_method_macro_doc!(
1749 "POST",
1750 post,
1751 create_user,
1752 CREATE_USER,
1753 "/users",
1754 "Create user logic"
1755);
1756http_method_macro_doc!(
1757 "PUT",
1758 put,
1759 put_user,
1760 PUT_USER,
1761 "/users/{id}",
1762 "Put user logic"
1763);
1764
1765/// Define a [fallback handler](https://pavex.dev/docs/guide/routing/).
1766///
1767/// A fallback handler is invoked when no other route matches the incoming request.
1768/// It's typically used to return a 404 Not Found response or redirect to a default page.
1769///
1770/// # Example
1771///
1772/// ```rust
1773/// use pavex::{fallback, Response};
1774///
1775/// #[fallback]
1776/// pub async fn not_found() -> Response {
1777/// Response::not_found()
1778/// .set_typed_body("The page you are looking for does not exist")
1779/// }
1780/// ```
1781///
1782/// # Guide
1783///
1784/// Check out the ["Routing"](https://pavex.dev/docs/guide/routing/)
1785/// section of Pavex's guide for a thorough introduction to routing
1786/// in Pavex applications.
1787///
1788/// # Registration
1789///
1790/// Use [`Blueprint::fallback`] to register the fallback handler with your [`Blueprint`].
1791///
1792/// The `#[fallback]` macro [generates a constant](#id) that you can use to refer to the
1793/// fallback handler when invoking [`Blueprint::fallback`].
1794///
1795/// # Arguments
1796///
1797/// The sections below provide an exhaustive list of all the arguments and flags supported by the [`fallback`][macro@fallback] macro:
1798///
1799/// | Name | Kind | Required |
1800/// |---------------------|----------|----------|
1801/// | [`id`](#id) | Argument | No |
1802///
1803/// ## `id`
1804///
1805/// By default, Pavex generates a constant named after your function
1806/// (converted to UPPER_SNAKE_CASE) that you use when registering the fallback handler.
1807///
1808/// The `id` argument allows you to customize the name of the generated constant.
1809///
1810/// ### Example
1811///
1812/// Using the default generated identifier:
1813///
1814/// ```rust
1815/// use pavex::{fallback, Blueprint, Response};
1816///
1817/// #[fallback]
1818/// pub async fn not_found() -> Response {
1819/// Response::not_found()
1820/// }
1821///
1822/// # fn main() {
1823/// let mut bp = Blueprint::new();
1824/// // The generated constant is named `NOT_FOUND`
1825/// bp.fallback(NOT_FOUND);
1826/// # }
1827/// ```
1828///
1829/// Using a custom identifier:
1830///
1831/// ```rust
1832/// use pavex::{fallback, Blueprint, Response};
1833///
1834/// #[fallback(id = "CUSTOM_404")]
1835/// // 👆 Custom identifier
1836/// pub async fn not_found() -> Response {
1837/// Response::not_found()
1838/// }
1839///
1840/// # fn main() {
1841/// let mut bp = Blueprint::new();
1842/// // Use the custom identifier when registering
1843/// bp.fallback(CUSTOM_404);
1844/// # }
1845/// ```
1846///
1847/// [`Blueprint::fallback`]: crate::Blueprint::fallback
1848/// [`Blueprint`]: crate::Blueprint
1849pub use pavex_macros::fallback;
1850
1851/// Define a [route](https://pavex.dev/docs/guide/routing/) for requests to a given path.
1852///
1853/// The `#[route]` macro can be used to define routes that match multiple HTTP methods, or
1854/// non-standard ones (e.g. `QUERY`).
1855/// Prefer one of the short-hand attributes if you need to match a standard HTTP method:
1856/// [`#[get]`](crate::get), [`#[post]`](crate::post), [`#[put]`](crate::put), [`#[patch]`](crate::patch),
1857/// [`#[delete]`](crate::delete), [`#[head]`](crate::head), and [`#[options]`](crate::options).
1858///
1859/// # Example: Multiple methods
1860///
1861/// ```rust
1862/// use pavex::{route, Response};
1863///
1864/// #[route(method = ["GET", "HEAD"], path = "/users/{id}")]
1865/// // 👆 Multiple methods
1866/// pub async fn get_or_head_user(/* */) -> Response {
1867/// // [...]
1868/// # Response::ok()
1869/// }
1870/// ```
1871///
1872/// # Guide
1873///
1874/// Check out the ["Routing"](https://pavex.dev/docs/guide/routing/)
1875/// section of Pavex's guide for a thorough introduction to routing
1876/// in Pavex applications.
1877///
1878/// # Registration
1879///
1880/// You can register a route with your application in two ways:
1881/// - Use [`Blueprint::route`] to register a single route
1882/// - Use [`Blueprint::routes`] to register multiple routes in bulk
1883///
1884/// The `#[route]` macro [generates a constant](#id) that you can use to refer to the
1885/// route when invoking [`Blueprint::route`].
1886///
1887/// # Arguments
1888///
1889/// The sections below provide an exhaustive list of all the arguments supported by the [`route`][macro@route] macro:
1890///
1891/// | Name | Kind | Required |
1892/// |---------------------------|----------|----------|
1893/// | [`method`](#method) | Argument | Yes* |
1894/// | [`path`](#path) | Argument | Yes |
1895/// | [`id`](#id) | Argument | No |
1896/// | [`allow`](#allow) | Argument | No |
1897///
1898/// \* The `method` argument is required unless [`allow(any_method)`](#allow) is specified.
1899///
1900/// ## `method`
1901///
1902/// The `method` argument specifies the HTTP method(s) that this route will match.
1903/// You can specify a single method or multiple methods.
1904///
1905/// `method` is required unless you specified [`allow(any_method)`](#allow) to accept
1906/// any HTTP method.
1907///
1908/// ### Example
1909///
1910/// Single method:
1911///
1912/// ```rust
1913/// use pavex::{route, Response};
1914///
1915/// #[route(method = "POST", path = "/users/{id}")]
1916/// // 👆 Single method
1917/// pub async fn create_user(/* */) -> Response {
1918/// // [...]
1919/// # Response::ok()
1920/// }
1921/// ```
1922///
1923/// Multiple methods:
1924///
1925/// ```rust
1926/// use pavex::{route, Response};
1927///
1928/// #[route(method = ["GET", "HEAD"], path = "/users/{id}")]
1929/// // 👆 Multiple methods
1930/// pub async fn get_or_head_user(/* */) -> Response {
1931/// // [...]
1932/// # Response::ok()
1933/// }
1934/// ```
1935///
1936/// ## `path`
1937///
1938/// The `path` argument specifies the URL path pattern that this route will match.
1939///
1940/// The path can contain parameter placeholders in the format `{parameter_name}` that will
1941/// be extracted and passed to your handler function.
1942///
1943/// ### Example
1944///
1945/// ```rust
1946/// use pavex::{route, Response};
1947///
1948/// #[route(method = "GET", path = "/users/{id}/posts/{post_id}")]
1949/// // 👆 Path with multiple parameters
1950/// pub async fn get_user_post(/* */) -> Response {
1951/// // [...]
1952/// # Response::ok()
1953/// }
1954/// ```
1955///
1956/// ## `id`
1957///
1958/// By default, Pavex generates a constant named after your function
1959/// (converted to UPPER_SNAKE_CASE) that you use when registering the route.
1960///
1961/// The `id` argument allows you to customize the name of the generated constant.
1962///
1963/// ### Example
1964///
1965/// Using the default generated identifier:
1966///
1967/// ```rust
1968/// use pavex::{route, Response, Blueprint};
1969///
1970/// #[route(method = "GET", path = "/users/{id}")]
1971/// pub async fn get_user(/* */) -> Response {
1972/// // [...]
1973/// # Response::ok()
1974/// }
1975///
1976/// # fn main() {
1977/// let mut bp = Blueprint::new();
1978/// // The generated constant is named `GET_USER`
1979/// bp.route(GET_USER);
1980/// # }
1981/// ```
1982///
1983/// Using a custom identifier:
1984///
1985/// ```rust
1986/// use pavex::{route, Response, Blueprint};
1987///
1988/// #[route(method = "GET", path = "/users/{id}", id = "USER_ROUTE")]
1989/// // 👆 Custom identifier
1990/// pub async fn get_user(/* */) -> Response {
1991/// // [...]
1992/// # Response::ok()
1993/// }
1994///
1995/// # fn main() {
1996/// let mut bp = Blueprint::new();
1997/// // Use the custom identifier when registering
1998/// bp.route(USER_ROUTE);
1999/// # }
2000/// ```
2001///
2002/// ## `allow`
2003///
2004/// The `allow` argument can be used to enable additional behaviors for this route.
2005///
2006/// Currently, the following values are supported:
2007/// - `non_standard_methods`: Allow non-standard HTTP methods
2008/// - `any_method`: Match any HTTP method.
2009/// It matches non-standard methods if `non_standard_methods` is also enabled.
2010///
2011/// ### Example: Non-standard method
2012///
2013/// Allow non-standard methods:
2014///
2015/// ```rust
2016/// use pavex::{route, Response};
2017///
2018/// #[route(method = "QUERY", path = "/users", allow(non_standard_methods))]
2019/// // 👆 Allow non-standard methods
2020/// pub async fn query_users() -> Response {
2021/// // [...]
2022/// # Response::ok()
2023/// }
2024/// ```
2025///
2026/// ### Example: Any standard method
2027///
2028/// Allow any method (no need to specify `method`):
2029///
2030/// ```rust
2031/// use pavex::{route, Response};
2032///
2033/// #[route(path = "/webhook", allow(any_method))]
2034/// // 👆 Allow any HTTP method
2035/// pub async fn webhook() -> Response {
2036/// // [...]
2037/// # Response::ok()
2038/// }
2039/// ```
2040///
2041/// ### Example: Arbitrary methods
2042///
2043/// Allow any method, including non-standard ones:
2044///
2045/// ```rust
2046/// use pavex::{route, Response};
2047///
2048/// #[route(path = "/webhook", allow(any_method, non_standard_methods))]
2049/// // 👆 Allow any HTTP method, including non-standard ones
2050/// pub async fn webhook() -> Response {
2051/// // [...]
2052/// # Response::ok()
2053/// }
2054/// ```
2055///
2056/// [`Blueprint::route`]: crate::Blueprint::route
2057/// [`Blueprint::routes`]: crate::Blueprint::routes
2058pub use pavex_macros::route;
2059
2060/// A helper macro to support Pavex attributes on methods.
2061///
2062/// You must annotate the `impl` block with `#[methods]` whenever you want to add Pavex attributes
2063/// like `#[get]`, `#[request_scoped]`, or `#[error_handler]` to methods defined in that `impl` block.
2064///
2065/// Without `#[methods]`, Pavex will reject the annotated methods.
2066///
2067/// # Example
2068///
2069/// ```rust
2070/// use pavex::methods;
2071/// use pavex::Response;
2072///
2073/// pub struct UserService {
2074/// // [...]
2075/// };
2076///
2077/// #[methods] // Required for the macros below to work
2078/// impl UserService {
2079/// #[request_scoped]
2080/// pub fn new() -> Self {
2081/// // [...]
2082/// # Self {}
2083/// }
2084///
2085/// #[get(path = "/users/{id}")]
2086/// pub fn get_user(/* */) -> Result<Response, GetUserError> {
2087/// // [...]
2088/// # Ok(Response::ok())
2089/// }
2090///
2091/// #[post(path = "/users/{id}")]
2092/// pub fn create_user(/* */) -> Result<Response, CreateUserError> {
2093/// // [...]
2094/// # Ok(Response::ok())
2095/// }
2096/// }
2097/// # struct CreateUserError;
2098/// # struct GetUserError;
2099/// ```
2100///
2101/// # Supported Annotations
2102///
2103/// All Pavex attributes can be attached to both methods and functions.
2104pub use pavex_macros::methods;