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