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}}