rocket/local/
client.rs

1macro_rules! req_method {
2    ($import:literal, $NAME:literal, $f:ident, $method:expr) => (
3        req_method!(@
4            $import,
5            $NAME,
6            concat!("let req = client.", stringify!($f), r#"("/hello");"#),
7            $f,
8            $method
9        );
10    );
11
12    (@$import:literal, $NAME:literal, $use_it:expr, $f:ident, $method:expr) => (
13        /// Create a local `
14        #[doc = $NAME]
15        /// ` request to the URI `uri`.
16        ///
17        /// When dispatched, the request will be served by the instance of Rocket
18        /// within `self`. The request is not dispatched automatically. To actually
19        /// dispatch the request, call [`LocalRequest::dispatch()`] on the returned
20        /// request.
21        ///
22        /// # Example
23        ///
24        /// ```rust,no_run
25        #[doc = $import]
26        ///
27        /// # Client::_test(|client, _, _| {
28        /// let client: &Client = client;
29        #[doc = $use_it]
30        /// # });
31        /// ```
32        #[inline(always)]
33        pub fn $f<'c, 'u: 'c, U>(&'c self, uri: U) -> LocalRequest<'c>
34            where U: TryInto<Origin<'u>> + fmt::Display
35        {
36            self.req($method, uri)
37        }
38    )
39}
40
41macro_rules! pub_client_impl {
42    ($import:literal $(@$prefix:tt $suffix:tt)?) =>
43{
44    /// Construct a new `Client` from an instance of `Rocket` _with_ cookie
45    /// tracking. This is typically the desired mode of operation for testing.
46    ///
47    /// # Cookie Tracking
48    ///
49    /// With cookie tracking enabled, a `Client` propagates cookie changes made
50    /// by responses to previously dispatched requests. In other words,
51    /// succeeding requests reflect changes (additions and removals) made by any
52    /// prior responses.
53    ///
54    /// Cookie tracking requires synchronization between dispatches. **As such,
55    /// cookie tracking _should not_ be enabled if a local client is being used
56    /// to serve requests on multiple threads.**
57    ///
58    /// # Errors
59    ///
60    /// If launching the `Rocket` instance would fail, excepting network errors,
61    /// the `Error` is returned.
62    ///
63    /// ```rust,no_run
64    #[doc = $import]
65    ///
66    /// let rocket = rocket::build();
67    /// let client = Client::tracked(rocket);
68    /// ```
69    #[inline(always)]
70    pub $($prefix)? fn tracked<P: Phase>(rocket: Rocket<P>) -> Result<Self, Error> {
71        Self::_new(rocket, true) $(.$suffix)?
72    }
73
74    /// Construct a new `Client` from an instance of `Rocket` _without_
75    /// cookie tracking.
76    ///
77    /// # Cookie Tracking
78    ///
79    /// Unlike the [`tracked()`](Client::tracked()) constructor, a `Client`
80    /// returned from this method _does not_ automatically propagate cookie
81    /// changes and thus requires no synchronization between dispatches.
82    ///
83    /// # Errors
84    ///
85    /// If launching the `Rocket` instance would fail, excepting network
86    /// errors, the `Error` is returned.
87    ///
88    /// ```rust,no_run
89    #[doc = $import]
90    ///
91    /// let rocket = rocket::build();
92    /// let client = Client::untracked(rocket);
93    /// ```
94    pub $($prefix)? fn untracked<P: Phase>(rocket: Rocket<P>) -> Result<Self, Error> {
95        Self::_new(rocket, false) $(.$suffix)?
96    }
97
98    /// Terminates `Client` by initiating a graceful shutdown via
99    /// [`Shutdown::notify()`] and running shutdown fairings.
100    ///
101    /// This method _must_ be called on a `Client` if graceful shutdown is
102    /// required for testing as `Drop` _does not_ signal `Shutdown` nor run
103    /// shutdown fairings. Returns the instance of `Rocket` being managed by
104    /// this client after all shutdown fairings run to completion.
105    ///
106    /// [`Shutdown::notify()`]: crate::Shutdown::notify()
107    ///
108    /// ```rust,no_run
109    #[doc = $import]
110    ///
111    /// # fn f(client: Client) {
112    /// let client: Client = client;
113    /// let rocket = client.terminate();
114    /// # }
115    /// ```
116    #[inline(always)]
117    pub $($prefix)? fn terminate(self) -> Rocket<Ignite> {
118        Self::_terminate(self) $(.$suffix)?
119    }
120
121    #[doc(hidden)]
122    pub $($prefix)? fn debug_with(routes: Vec<crate::Route>) -> Result<Self, Error> {
123        let rocket = crate::custom(crate::Config::debug_default());
124        Self::debug(rocket.mount("/", routes)) $(.$suffix)?
125    }
126
127    #[doc(hidden)]
128    pub $($prefix)? fn debug(rocket: Rocket<crate::Build>) -> Result<Self, Error> {
129        use crate::config;
130
131        let figment = rocket.figment().clone()
132            .merge((config::Config::LOG_LEVEL, config::LogLevel::Debug))
133            .select(config::Config::DEBUG_PROFILE);
134
135        Self::tracked(rocket.configure(figment)) $(.$suffix)?
136    }
137
138    /// Deprecated alias to [`Client::tracked()`].
139    #[deprecated(
140        since = "0.5.0",
141        note = "choose between `Client::untracked()` and `Client::tracked()`"
142    )]
143    pub $($prefix)? fn new<P: Phase>(rocket: Rocket<P>) -> Result<Self, Error> {
144        Self::tracked(rocket) $(.$suffix)?
145    }
146
147    /// Returns a reference to the `Rocket` this client is creating requests
148    /// for.
149    ///
150    /// # Example
151    ///
152    /// ```rust
153    #[doc = $import]
154    ///
155    /// # Client::_test(|client, _, _| {
156    /// let client: &Client = client;
157    /// let rocket = client.rocket();
158    /// # });
159    /// ```
160    #[inline(always)]
161    pub fn rocket(&self) -> &Rocket<Orbit> {
162        &*self._rocket()
163    }
164
165    /// Returns a cookie jar containing all of the cookies this client is
166    /// currently tracking.
167    ///
168    /// If cookie tracking is disabled, the returned jar will always be empty.
169    /// Otherwise, it will contains all of the cookies collected from responses
170    /// to requests dispatched by this client that have not expired.
171    ///
172    /// # Example
173    ///
174    /// ```rust
175    #[doc = $import]
176    ///
177    /// # Client::_test(|client, _, _| {
178    /// let client: &Client = client;
179    /// let cookie = client.cookies();
180    /// # });
181    /// ```
182    #[inline(always)]
183    pub fn cookies(&self) -> crate::http::CookieJar<'_> {
184        let config = &self.rocket().config();
185        let jar = self._with_raw_cookies(|jar| jar.clone());
186        crate::http::CookieJar::from(jar, config)
187    }
188
189    req_method!($import, "GET", get, Method::Get);
190    req_method!($import, "PUT", put, Method::Put);
191    req_method!($import, "POST", post, Method::Post);
192    req_method!($import, "DELETE", delete, Method::Delete);
193    req_method!($import, "OPTIONS", options, Method::Options);
194    req_method!($import, "HEAD", head, Method::Head);
195    req_method!($import, "PATCH", patch, Method::Patch);
196
197    /// Create a local `GET` request to the URI `uri`.
198    ///
199    /// When dispatched, the request will be served by the instance of
200    /// Rocket within `self`. The request is not dispatched automatically.
201    /// To actually dispatch the request, call [`LocalRequest::dispatch()`]
202    /// on the returned request.
203    ///
204    /// # Example
205    ///
206    /// ```rust,no_run
207    #[doc = $import]
208    /// use rocket::http::Method;
209    ///
210    /// # Client::_test(|client, _, _| {
211    /// let client: &Client = client;
212    /// client.req(Method::Get, "/hello");
213    /// # });
214    /// ```
215    #[inline(always)]
216    pub fn req<'c, 'u: 'c, U>(
217        &'c self,
218        method: Method,
219        uri: U
220    ) -> LocalRequest<'c>
221        where U: TryInto<Origin<'u>> + fmt::Display
222    {
223        self._req(method, uri)
224    }
225
226    #[cfg(test)]
227    #[allow(dead_code)]
228    fn _ensure_impls_exist() {
229        fn is_send<T: Send>() {}
230        is_send::<Self>();
231
232        fn is_debug<T: std::fmt::Debug>() {}
233        is_debug::<Self>();
234    }
235}}