rocket_community/rocket.rs
1use std::any::Any;
2use std::fmt;
3use std::future::Future;
4use std::ops::{Deref, DerefMut};
5use std::panic::Location;
6use std::sync::Arc;
7use std::time::Duration;
8
9use either::Either;
10use figment::{Figment, Provider};
11use futures::TryFutureExt;
12
13use crate::error::{Error, ErrorKind};
14use crate::fairing::{Fairing, Fairings};
15use crate::http::ext::IntoOwned;
16use crate::http::uri::Origin;
17use crate::listener::{Bind, DefaultListener, Endpoint, Listener};
18use crate::phase::{Build, Building, Ignite, Igniting, Orbit, Orbiting, Phase};
19use crate::phase::{State, StateRef, StateRefMut, Stateful};
20use crate::router::Router;
21use crate::shutdown::{Shutdown, Stages};
22use crate::trace::{Trace, TraceAll};
23use crate::{sentinel, shield::Shield, Catcher, Config, Route};
24
25/// The application server itself.
26///
27/// # Phases
28///
29/// A `Rocket` instance represents a web server and its state. It progresses
30/// through three statically-enforced phases: build, ignite, orbit.
31///
32/// * **Build**: _application and server configuration_
33///
34/// This phase enables:
35///
36/// * setting configuration options
37/// * mounting/registering routes/catchers
38/// * managing state
39/// * attaching fairings
40///
41/// This is the _only_ phase in which an instance can be modified. To finalize
42/// changes, an instance is ignited via [`Rocket::ignite()`], progressing it
43/// into the _ignite_ phase, or directly launched into orbit with
44/// [`Rocket::launch()`] which progress the instance through ignite into
45/// orbit.
46///
47/// * **Ignite**: _verification and finalization of configuration_
48///
49/// An instance in the [`Ignite`] phase is in its final configuration,
50/// available via [`Rocket::config()`]. Barring user-supplied interior
51/// mutation, application state is guaranteed to remain unchanged beyond this
52/// point. An instance in the ignite phase can be launched into orbit to serve
53/// requests via [`Rocket::launch()`].
54///
55/// * **Orbit**: _a running web server_
56///
57/// An instance in the [`Orbit`] phase represents a _running_ application,
58/// actively serving requests.
59///
60/// # Launching
61///
62/// To launch a `Rocket` application, the suggested approach is to return an
63/// instance of `Rocket<Build>` from a function named `rocket` marked with the
64/// [`#[launch]`](crate::launch) attribute:
65///
66/// ```rust,no_run
67/// # extern crate rocket_community as rocket;
68/// # use rocket::launch;
69/// #[launch]
70/// fn rocket() -> _ {
71/// rocket::build()
72/// }
73/// ```
74///
75/// This generates a `main` function with an `async` runtime that runs the
76/// returned `Rocket` instance.
77///
78/// * **Manual Launching**
79///
80/// To launch an instance of `Rocket`, it _must_ progress through all three
81/// phases. To progress into the ignite or launch phases, a tokio `async`
82/// runtime is required. The [`#[main]`](crate::main) attribute initializes a
83/// Rocket-specific tokio runtime and runs the attributed `async fn` inside of
84/// it:
85///
86/// ```rust,no_run
87/// # extern crate rocket_community as rocket;
88/// #[rocket::main]
89/// async fn main() -> Result<(), rocket::Error> {
90/// let _rocket = rocket::build()
91/// .ignite().await?
92/// .launch().await?;
93///
94/// Ok(())
95/// }
96/// ```
97///
98/// Note that [`Rocket::launch()`] automatically progresses an instance of
99/// `Rocket` from any phase into orbit:
100///
101/// ```rust,no_run
102/// # extern crate rocket_community as rocket;
103/// #[rocket::main]
104/// async fn main() -> Result<(), rocket::Error> {
105/// let _rocket = rocket::build().launch().await?;
106/// Ok(())
107/// }
108/// ```
109///
110/// For extreme and rare cases in which [`#[main]`](crate::main) imposes
111/// obstinate restrictions, use [`rocket::execute()`](crate::execute()) to
112/// execute Rocket's `launch()` future.
113///
114/// * **Automatic Launching**
115///
116/// Manually progressing an instance of Rocket though its phases is only
117/// necessary when either an instance's finalized state is to be inspected (in
118/// the _ignite_ phase) or the instance is expected to deorbit due to
119/// [`Rocket::shutdown()`]. In the more common case when neither is required,
120/// the [`#[launch]`](crate::launch) attribute can be used. When applied to a
121/// function that returns a `Rocket<Build>`, it automatically initializes an
122/// `async` runtime and launches the function's returned instance:
123///
124/// ```rust,no_run
125/// # extern crate rocket_community as rocket;
126/// # use rocket::launch;
127/// use rocket::{Rocket, Build};
128///
129/// #[launch]
130/// fn rocket() -> Rocket<Build> {
131/// rocket::build()
132/// }
133/// ```
134///
135/// To avoid needing to import _any_ items in the common case, the `launch`
136/// attribute will infer a return type written as `_` as `Rocket<Build>`:
137///
138/// ```rust,no_run
139/// # extern crate rocket_community as rocket;
140/// # use rocket::launch;
141/// #[launch]
142/// fn rocket() -> _ {
143/// rocket::build()
144/// }
145/// ```
146pub struct Rocket<P: Phase>(pub(crate) P::State);
147
148impl Rocket<Build> {
149 /// Create a new `Rocket` application using the default configuration
150 /// provider, [`Config::figment()`].
151 ///
152 /// This method is typically called through the
153 /// [`rocket::build()`](crate::build) alias.
154 ///
155 /// # Examples
156 ///
157 /// ```rust
158 /// # extern crate rocket_community as rocket;
159 /// # use rocket::launch;
160 /// #[launch]
161 /// fn rocket() -> _ {
162 /// rocket::build()
163 /// }
164 /// ```
165 #[must_use]
166 #[inline(always)]
167 pub fn build() -> Self {
168 Rocket::custom(Config::figment())
169 }
170
171 /// Creates a new `Rocket` application using the supplied configuration
172 /// provider.
173 ///
174 /// This method is typically called through the
175 /// [`rocket::custom()`](crate::custom()) alias.
176 ///
177 /// # Example
178 ///
179 /// ```rust
180 /// # extern crate rocket_community as rocket;
181 /// # use rocket::launch;
182 /// use rocket::figment::{Figment, providers::{Toml, Env, Format}};
183 ///
184 /// #[launch]
185 /// fn rocket() -> _ {
186 /// let figment = Figment::from(rocket::Config::default())
187 /// .merge(Toml::file("MyApp.toml").nested())
188 /// .merge(Env::prefixed("MY_APP_").global());
189 ///
190 /// rocket::custom(figment)
191 /// }
192 /// ```
193 #[must_use]
194 pub fn custom<T: Provider>(provider: T) -> Self {
195 Rocket::<Build>(Building::default())
196 .reconfigure(provider)
197 .attach(Shield::default())
198 }
199
200 /// Overrides the current configuration provider with `provider`.
201 ///
202 /// The default provider, or a provider previously set with
203 /// [`Rocket::custom()`] or [`Rocket::reconfigure()`], is overridden by
204 /// `provider`.
205 ///
206 /// # Example
207 ///
208 /// ```rust
209 /// # extern crate rocket_community as rocket;
210 /// use rocket::config::{Config, Ident};
211 /// # use std::net::Ipv4Addr;
212 /// # use std::path::{Path, PathBuf};
213 /// # type Result = std::result::Result<(), rocket::Error>;
214 ///
215 /// let config = Config {
216 /// ident: Ident::try_new("MyServer").expect("valid ident"),
217 /// temp_dir: "/tmp/config-example".into(),
218 /// ..Config::debug_default()
219 /// };
220 ///
221 /// # let _: Result = rocket::async_test(async move {
222 /// let rocket = rocket::custom(&config).ignite().await?;
223 /// assert_eq!(rocket.config().ident.as_str(), Some("MyServer"));
224 /// assert_eq!(rocket.config().temp_dir.relative(), Path::new("/tmp/config-example"));
225 ///
226 /// // Create a new figment which modifies _some_ keys the existing figment:
227 /// let figment = rocket.figment().clone()
228 /// .merge((Config::IDENT, "Example"));
229 ///
230 /// let rocket = rocket::custom(&config)
231 /// .reconfigure(figment)
232 /// .ignite().await?;
233 ///
234 /// assert_eq!(rocket.config().ident.as_str(), Some("Example"));
235 /// assert_eq!(rocket.config().temp_dir.relative(), Path::new("/tmp/config-example"));
236 /// # Ok(())
237 /// # });
238 /// ```
239 #[must_use]
240 pub fn reconfigure<T: Provider>(mut self, provider: T) -> Self {
241 // We initialize the logger here so that logging from fairings and so on
242 // are visible; we use the final config to set a max log-level in ignite
243 self.figment = Figment::from(provider);
244 crate::trace::init(Config::try_from(&self.figment).ok().as_ref());
245 span_trace!("reconfigure" => self.figment().trace_trace());
246
247 self
248 }
249
250 #[track_caller]
251 fn load<'a, B, T, F, M>(mut self, kind: &str, base: B, items: Vec<T>, m: M, f: F) -> Self
252 where
253 B: TryInto<Origin<'a>> + Clone + fmt::Display,
254 B::Error: fmt::Display,
255 M: Fn(&Origin<'a>, T) -> T,
256 F: Fn(&mut Self, T),
257 T: Clone + Trace,
258 {
259 let mut base = match base.clone().try_into() {
260 Ok(origin) => origin.into_owned(),
261 Err(e) => {
262 error!(%base, location = %Location::caller(), "invalid {kind} base uri: {e}");
263 panic!("aborting due to {} base error", kind);
264 }
265 };
266
267 if base.query().is_some() {
268 warn!(%base, location = %Location::caller(), "query in {kind} base is ignored");
269 base.clear_query();
270 }
271
272 for unmounted_item in items {
273 f(&mut self, m(&base, unmounted_item.clone()))
274 }
275
276 self
277 }
278
279 /// Mounts all of the `routes` at the given `base` mount point.
280 ///
281 /// A route _mounted_ at `base` has an effective URI of `base/route`, where
282 /// `route` is the route URI. In other words, `base` is added as a prefix to
283 /// the route's URI. The URI resulting from joining the `base` URI and the
284 /// route URI is called the route's _effective URI_, as this is the URI used
285 /// for request matching during routing.
286 ///
287 /// A `base` URI is not allowed to have a query part. If a `base` _does_
288 /// have a query part, it is ignored when producing the effective URI.
289 ///
290 /// A `base` may have an optional trailing slash. A route with a URI path of
291 /// `/` (and any optional query) mounted at a `base` has an effective URI
292 /// equal to the `base` (plus any optional query). That is, if the base has
293 /// a trailing slash, the effective URI path has a trailing slash, and
294 /// otherwise it does not. Routes with URI paths other than `/` are not
295 /// effected by trailing slashes in their corresponding mount point.
296 ///
297 /// As concrete examples, consider the following table:
298 ///
299 /// | mount point | route URI | effective URI |
300 /// |-------------|-----------|---------------|
301 /// | `/` | `/foo` | `/foo` |
302 /// | `/` | `/foo/` | `/foo/` |
303 /// | `/foo` | `/` | `/foo` |
304 /// | `/foo` | `/?bar` | `/foo?bar` |
305 /// | `/foo` | `/bar` | `/foo/bar` |
306 /// | `/foo` | `/bar/` | `/foo/bar/` |
307 /// | `/foo/` | `/` | `/foo/` |
308 /// | `/foo/` | `/bar` | `/foo/bar` |
309 /// | `/foo/` | `/?bar` | `/foo/?bar` |
310 /// | `/foo/bar` | `/` | `/foo/bar` |
311 /// | `/foo/bar/` | `/` | `/foo/bar/` |
312 /// | `/foo/?bar` | `/` | `/foo/` |
313 /// | `/foo/?bar` | `/baz` | `/foo/baz` |
314 /// | `/foo/?bar` | `/baz/` | `/foo/baz/` |
315 ///
316 /// # Panics
317 ///
318 /// Panics if either:
319 ///
320 /// * the `base` mount point is not a valid origin URI without dynamic
321 /// parameters
322 ///
323 /// * any route URI is not a valid origin URI. (**Note:** _This kind of
324 /// panic is guaranteed not to occur if the routes were generated using
325 /// Rocket's code generation._)
326 ///
327 /// # Examples
328 ///
329 /// Use the `routes!` macro to mount routes created using the code
330 /// generation facilities. Requests to both `/world` and `/hello/world` URI
331 /// will be dispatched to the `hi` route.
332 ///
333 /// ```rust,no_run
334 /// # #[macro_use] extern crate rocket_community as rocket;
335 /// #
336 /// #[get("/world")]
337 /// fn hi() -> &'static str {
338 /// "Hello!"
339 /// }
340 ///
341 /// #[launch]
342 /// fn rocket() -> _ {
343 /// rocket::build()
344 /// .mount("/", routes![hi])
345 /// .mount("/hello", routes![hi])
346 /// }
347 /// ```
348 ///
349 /// Manually create a route named `hi` at path `"/world"` mounted at base
350 /// `"/hello"`. Requests to the `/hello/world` URI will be dispatched to the
351 /// `hi` route.
352 ///
353 /// ```rust
354 /// # #[macro_use] extern crate rocket_community as rocket;
355 /// use rocket::{Request, Route, Data, route};
356 /// use rocket::http::Method;
357 ///
358 /// fn hi<'r>(req: &'r Request, _: Data<'r>) -> route::BoxFuture<'r> {
359 /// route::Outcome::from(req, "Hello!").pin()
360 /// }
361 ///
362 /// #[launch]
363 /// fn rocket() -> _ {
364 /// let hi_route = Route::new(Method::Get, "/world", hi);
365 /// rocket::build().mount("/hello", vec![hi_route])
366 /// }
367 /// ```
368 #[must_use]
369 #[track_caller]
370 pub fn mount<'a, B, R>(self, base: B, routes: R) -> Self
371 where
372 B: TryInto<Origin<'a>> + Clone + fmt::Display,
373 B::Error: fmt::Display,
374 R: Into<Vec<Route>>,
375 {
376 self.load(
377 "route",
378 base,
379 routes.into(),
380 |base, route| route.rebase(base.clone()),
381 |r, route| r.0.routes.push(route),
382 )
383 }
384
385 /// Registers all of the catchers in the supplied vector, scoped to `base`.
386 ///
387 /// # Panics
388 ///
389 /// Panics if `base` is not a valid static path: a valid origin URI without
390 /// dynamic parameters.
391 ///
392 /// # Examples
393 ///
394 /// ```rust,no_run
395 /// # #[macro_use] extern crate rocket_community as rocket;
396 /// use rocket::Request;
397 ///
398 /// #[catch(500)]
399 /// fn internal_error() -> &'static str {
400 /// "Whoops! Looks like we messed up."
401 /// }
402 ///
403 /// #[catch(404)]
404 /// fn not_found(req: &Request) -> String {
405 /// format!("I couldn't find '{}'. Try something else?", req.uri())
406 /// }
407 ///
408 /// #[launch]
409 /// fn rocket() -> _ {
410 /// rocket::build().register("/", catchers![internal_error, not_found])
411 /// }
412 /// ```
413 #[must_use]
414 pub fn register<'a, B, C>(self, base: B, catchers: C) -> Self
415 where
416 B: TryInto<Origin<'a>> + Clone + fmt::Display,
417 B::Error: fmt::Display,
418 C: Into<Vec<Catcher>>,
419 {
420 self.load(
421 "catcher",
422 base,
423 catchers.into(),
424 |base, catcher| catcher.rebase(base.clone()),
425 |r, catcher| r.0.catchers.push(catcher),
426 )
427 }
428
429 /// Add `state` to the state managed by this instance of Rocket.
430 ///
431 /// This method can be called any number of times as long as each call
432 /// refers to a different `T`.
433 ///
434 /// Managed state can be retrieved by any request handler via the
435 /// [`State`](crate::State) request guard. In particular, if a value of type `T`
436 /// is managed by Rocket, adding `State<T>` to the list of arguments in a
437 /// request handler instructs Rocket to retrieve the managed value.
438 ///
439 /// # Panics
440 ///
441 /// Panics if state of type `T` is already being managed.
442 ///
443 /// # Example
444 ///
445 /// ```rust,no_run
446 /// # #[macro_use] extern crate rocket_community as rocket;
447 /// use rocket::State;
448 ///
449 /// struct MyInt(isize);
450 /// struct MyString(String);
451 ///
452 /// #[get("/int")]
453 /// fn int(state: &State<MyInt>) -> String {
454 /// format!("The stateful int is: {}", state.0)
455 /// }
456 ///
457 /// #[get("/string")]
458 /// fn string(state: &State<MyString>) -> &str {
459 /// &state.0
460 /// }
461 ///
462 /// #[launch]
463 /// fn rocket() -> _ {
464 /// rocket::build()
465 /// .manage(MyInt(10))
466 /// .manage(MyString("Hello, managed state!".to_string()))
467 /// .mount("/", routes![int, string])
468 /// }
469 /// ```
470 #[must_use]
471 pub fn manage<T>(self, state: T) -> Self
472 where
473 T: Send + Sync + 'static,
474 {
475 let type_name = std::any::type_name::<T>();
476 if !self.state.set(state) {
477 error!("state for type '{}' is already being managed", type_name);
478 panic!("aborting due to duplicated managed state");
479 }
480
481 self
482 }
483
484 /// Attaches a fairing to this instance of Rocket. No fairings are eagerly
485 /// executed; fairings are executed at their appropriate time.
486 ///
487 /// If the attached fairing is a [singleton] and a fairing of the same type
488 /// has already been attached, this fairing replaces it. Otherwise the
489 /// fairing gets attached without replacing any existing fairing.
490 ///
491 /// [singleton]: crate::fairing::Fairing#singletons
492 ///
493 /// # Example
494 ///
495 /// ```rust,no_run
496 /// # #[macro_use] extern crate rocket_community as rocket;
497 /// use rocket::Rocket;
498 /// use rocket::fairing::AdHoc;
499 ///
500 /// #[launch]
501 /// fn rocket() -> _ {
502 /// rocket::build()
503 /// .attach(AdHoc::on_liftoff("Liftoff Message", |_| Box::pin(async {
504 /// println!("We have liftoff!");
505 /// })))
506 /// }
507 /// ```
508 #[must_use]
509 pub fn attach<F: Fairing>(mut self, fairing: F) -> Self {
510 self.fairings.add(Box::new(fairing));
511 self
512 }
513
514 /// Returns a `Future` that transitions this instance of `Rocket` into the
515 /// _ignite_ phase.
516 ///
517 /// When `await`ed, the future runs all _ignite_ fairings in serial,
518 /// [attach](Rocket::attach()) order, and verifies that `self` represents a
519 /// valid instance of `Rocket` ready for launch. This means that:
520 ///
521 /// * All ignite fairings succeeded.
522 /// * A valid [`Config`] was extracted from [`Rocket::figment()`].
523 /// * If `secrets` are enabled, the extracted `Config` contains a safe
524 /// secret key.
525 /// * There are no [`Route#collisions`] or [`Catcher#collisions`]
526 /// collisions.
527 /// * No [`Sentinel`](crate::Sentinel) triggered an abort.
528 ///
529 /// If any of these conditions fail to be met, a respective [`Error`] is
530 /// returned.
531 ///
532 /// [configured]: Rocket::figment()
533 ///
534 /// # Example
535 ///
536 /// ```rust
537 /// # extern crate rocket_community as rocket;
538 /// use rocket::fairing::AdHoc;
539 ///
540 /// #[rocket::main]
541 /// async fn main() -> Result<(), rocket::Error> {
542 /// let rocket = rocket::build()
543 /// # .reconfigure(rocket::Config::debug_default())
544 /// .attach(AdHoc::on_ignite("Manage State", |rocket| async move {
545 /// rocket.manage(String::from("managed string"))
546 /// }));
547 ///
548 /// // No fairings are run until ignition occurs.
549 /// assert!(rocket.state::<String>().is_none());
550 ///
551 /// let rocket = rocket.ignite().await?;
552 /// assert_eq!(rocket.state::<String>().unwrap(), "managed string");
553 ///
554 /// Ok(())
555 /// }
556 /// ```
557 pub async fn ignite(mut self) -> Result<Rocket<Ignite>, Error> {
558 self = Fairings::handle_ignite(self).await;
559 self.fairings
560 .audit()
561 .map_err(|f| ErrorKind::FailedFairings(f.to_vec()))?;
562
563 // Extract the configuration; initialize default trace subscriber.
564 #[allow(unused_mut)]
565 let mut config = Config::try_from(&self.figment).map_err(ErrorKind::Config)?;
566 crate::trace::init(&config);
567
568 // Check for safely configured secrets.
569 #[cfg(feature = "secrets")]
570 if !config.secret_key.is_provided() {
571 if config.profile != Config::DEBUG_PROFILE {
572 return Err(Error::new(ErrorKind::InsecureSecretKey(
573 config.profile.clone(),
574 )));
575 }
576
577 if config.secret_key.is_zero() {
578 config.secret_key = crate::config::SecretKey::generate()
579 .unwrap_or_else(crate::config::SecretKey::zero);
580 }
581 }
582
583 // Initialize the router; check for collisions.
584 let mut router = Router::new();
585 self.routes
586 .clone()
587 .into_iter()
588 .for_each(|r| router.routes.push(r));
589 self.catchers
590 .clone()
591 .into_iter()
592 .for_each(|c| router.catchers.push(c));
593 let router = router.finalize().map_err(|(r, c)| ErrorKind::Collisions {
594 routes: r,
595 catchers: c,
596 })?;
597
598 // Finally, freeze managed state for faster access later.
599 self.state.freeze();
600
601 // Log everything we know: config, routes, catchers, fairings.
602 // TODO: Store/print managed state type names?
603 let fairings = self.fairings.unique_set();
604 span_info!("config", profile = %self.figment().profile() => {
605 config.trace_info();
606 self.figment().trace_debug();
607 });
608
609 span_info!("routes", count = self.routes.len() => self.routes().trace_all_info());
610 span_info!("catchers", count = self.catchers.len() => self.catchers().trace_all_info());
611 span_info!("fairings", count = fairings.len() => fairings.trace_all_info());
612
613 // Ignite the rocket.
614 let rocket: Rocket<Ignite> = Rocket(Igniting {
615 shutdown: Stages::new(),
616 figment: self.0.figment,
617 fairings: self.0.fairings,
618 state: self.0.state,
619 router,
620 config,
621 });
622
623 // Query the sentinels, abort if requested.
624 let sentinels = rocket.routes().flat_map(|r| r.sentinels.iter());
625 sentinel::query(sentinels, &rocket).map_err(ErrorKind::SentinelAborts)?;
626
627 Ok(rocket)
628 }
629}
630
631impl Rocket<Ignite> {
632 /// Returns the finalized, active configuration. This is guaranteed to
633 /// remain stable through ignition and into orbit.
634 ///
635 /// # Example
636 ///
637 /// ```rust,no_run
638 /// # extern crate rocket_community as rocket;
639 /// #[rocket::main]
640 /// async fn main() -> Result<(), rocket::Error> {
641 /// let rocket = rocket::build().ignite().await?;
642 /// let config = rocket.config();
643 /// Ok(())
644 /// }
645 /// ```
646 pub fn config(&self) -> &Config {
647 &self.config
648 }
649
650 /// Returns a handle which can be used to trigger a shutdown and detect a
651 /// triggered shutdown.
652 ///
653 /// A completed graceful shutdown resolves the future returned by
654 /// [`Rocket::launch()`]. If [`Shutdown::notify()`] is called _before_ an
655 /// instance is launched, it will be immediately shutdown after liftoff. See
656 /// [`Shutdown`] and [`ShutdownConfig`](crate::config::ShutdownConfig) for
657 /// details on graceful shutdown.
658 ///
659 /// # Example
660 ///
661 /// ```rust,no_run
662 /// # extern crate rocket_community as rocket;
663 /// # use std::time::Duration;
664 /// use rocket::tokio::{self, time};
665 ///
666 /// #[rocket::main]
667 /// async fn main() -> Result<(), rocket::Error> {
668 /// let rocket = rocket::build().ignite().await?;
669 ///
670 /// let shutdown = rocket.shutdown();
671 /// tokio::spawn(async move {
672 /// time::sleep(time::Duration::from_secs(5)).await;
673 /// shutdown.notify();
674 /// });
675 ///
676 /// // The `launch()` future resolves after ~5 seconds.
677 /// let result = rocket.launch().await;
678 /// assert!(result.is_ok());
679 ///
680 /// Ok(())
681 /// }
682 /// ```
683 pub fn shutdown(&self) -> Shutdown {
684 self.shutdown.start.clone()
685 }
686
687 pub(crate) fn into_orbit(self, endpoints: Vec<Endpoint>) -> Rocket<Orbit> {
688 Rocket(Orbiting {
689 endpoints,
690 router: self.0.router,
691 fairings: self.0.fairings,
692 figment: self.0.figment,
693 config: self.0.config,
694 state: self.0.state,
695 shutdown: self.0.shutdown,
696 })
697 }
698
699 async fn _local_launch(self, endpoint: Endpoint) -> Rocket<Orbit> {
700 let rocket = self.into_orbit(vec![endpoint]);
701 Rocket::liftoff(&rocket).await;
702 rocket
703 }
704
705 async fn _launch<L: Listener + 'static>(self, listener: L) -> Result<Rocket<Ignite>, Error> {
706 let rocket = self
707 .listen_and_serve(listener, |rocket| async move {
708 let rocket = Arc::new(rocket);
709
710 rocket.shutdown.spawn_listener(&rocket.config.shutdown);
711 if let Err(e) = tokio::spawn(Rocket::liftoff(rocket.clone())).await {
712 let rocket = rocket.try_wait_shutdown().await.map(Box::new);
713 return Err(ErrorKind::Liftoff(rocket, e).into());
714 }
715
716 Ok(rocket)
717 })
718 .await?;
719
720 Ok(rocket
721 .try_wait_shutdown()
722 .await
723 .map_err(ErrorKind::Shutdown)?)
724 }
725}
726
727impl Rocket<Orbit> {
728 /// Rocket wraps all connections in a `CancellableIo` struct, an internal
729 /// structure that gracefully closes I/O when it receives a signal. That
730 /// signal is the `shutdown` future. When the future resolves,
731 /// `CancellableIo` begins to terminate in grace, mercy, and finally force
732 /// close phases. Since all connections are wrapped in `CancellableIo`, this
733 /// eventually ends all I/O.
734 ///
735 /// At that point, unless a user spawned an infinite, stand-alone task that
736 /// isn't monitoring `Shutdown`, all tasks should resolve. This means that
737 /// all instances of the shared `Arc<Rocket>` are dropped and we can return
738 /// the owned instance of `Rocket`.
739 ///
740 /// Unfortunately, the Hyper `server` future resolves as soon as it has
741 /// finished processing requests without respect for ongoing responses. That
742 /// is, `server` resolves even when there are running tasks that are
743 /// generating a response. So, `server` resolving implies little to nothing
744 /// about the state of connections. As a result, we depend on the timing of
745 /// grace + mercy + some buffer to determine when all connections should be
746 /// closed, thus all tasks should be complete, thus all references to
747 /// `Arc<Rocket>` should be dropped and we can get back a unique reference.
748 async fn try_wait_shutdown(self: Arc<Self>) -> Result<Rocket<Ignite>, Arc<Self>> {
749 info!("Shutting down. Waiting for shutdown fairings and pending I/O...");
750 tokio::spawn({
751 let rocket = self.clone();
752 async move { rocket.fairings.handle_shutdown(&rocket).await }
753 });
754
755 let config = &self.config.shutdown;
756 let wait = Duration::from_micros(250);
757 for period in [wait, config.grace(), wait, config.mercy(), wait * 4] {
758 if Arc::strong_count(&self) == 1 {
759 break;
760 }
761 tokio::time::sleep(period).await;
762 }
763
764 match Arc::try_unwrap(self) {
765 Ok(rocket) => {
766 info!("Graceful shutdown completed successfully.");
767 Ok(rocket.deorbit())
768 }
769 Err(rocket) => {
770 warn!("Shutdown failed: outstanding background I/O.");
771 Err(rocket)
772 }
773 }
774 }
775
776 pub(crate) fn deorbit(self) -> Rocket<Ignite> {
777 Rocket(Igniting {
778 router: self.0.router,
779 fairings: self.0.fairings,
780 figment: self.0.figment,
781 config: self.0.config,
782 state: self.0.state,
783 shutdown: self.0.shutdown,
784 })
785 }
786
787 pub(crate) async fn liftoff<R: Deref<Target = Self>>(rocket: R) {
788 let rocket = rocket.deref();
789 rocket.fairings.handle_liftoff(rocket).await;
790
791 if !crate::running_within_rocket_async_rt().await {
792 warn!(
793 "Rocket is executing inside of a custom runtime.\n\
794 Rocket's runtime is enabled via `#[rocket::main]` or `#[launch]`\n\
795 Forced shutdown is disabled. Runtime settings may be suboptimal."
796 );
797 }
798
799 tracing::info!(name: "liftoff", endpoint = %rocket.endpoints[0]);
800 }
801
802 /// Returns the finalized, active configuration. This is guaranteed to
803 /// remain stable after [`Rocket::ignite()`], through ignition and into
804 /// orbit.
805 ///
806 /// # Example
807 ///
808 /// ```rust,no_run
809 /// # #[macro_use] extern crate rocket_community as rocket;
810 /// use rocket::fairing::AdHoc;
811 ///
812 /// #[launch]
813 /// fn rocket() -> _ {
814 /// rocket::build()
815 /// .attach(AdHoc::on_liftoff("Config", |rocket| Box::pin(async move {
816 /// println!("Rocket launch config: {:?}", rocket.config());
817 /// })))
818 /// }
819 /// ```
820 pub fn config(&self) -> &Config {
821 &self.config
822 }
823
824 pub fn endpoints(&self) -> impl Iterator<Item = &Endpoint> {
825 self.endpoints.iter()
826 }
827
828 /// Returns a handle which can be used to trigger a shutdown and detect a
829 /// triggered shutdown.
830 ///
831 /// A completed graceful shutdown resolves the future returned by
832 /// [`Rocket::launch()`]. See [`Shutdown`] and
833 /// [`ShutdownConfig`](crate::config::ShutdownConfig) for details on
834 /// graceful shutdown.
835 ///
836 /// # Example
837 ///
838 /// ```rust,no_run
839 /// # #[macro_use] extern crate rocket_community as rocket;
840 /// use rocket::tokio::{self, time};
841 /// use rocket::fairing::AdHoc;
842 ///
843 /// #[launch]
844 /// fn rocket() -> _ {
845 /// rocket::build()
846 /// .attach(AdHoc::on_liftoff("Shutdown", |rocket| Box::pin(async move {
847 /// let shutdown = rocket.shutdown();
848 /// tokio::spawn(async move {
849 /// time::sleep(time::Duration::from_secs(5)).await;
850 /// shutdown.notify();
851 /// });
852 /// })))
853 /// }
854 /// ```
855 pub fn shutdown(&self) -> Shutdown {
856 self.shutdown.start.clone()
857 }
858}
859
860impl<P: Phase> Rocket<P> {
861 /// Returns an iterator over all of the routes mounted on this instance of
862 /// Rocket. The order is unspecified.
863 ///
864 /// # Example
865 ///
866 /// ```rust
867 /// # extern crate rocket_community as rocket;
868 /// # use rocket::*;
869 /// use rocket::Rocket;
870 /// use rocket::fairing::AdHoc;
871 ///
872 /// #[get("/hello")]
873 /// fn hello() -> &'static str {
874 /// "Hello, world!"
875 /// }
876 ///
877 /// let rocket = rocket::build()
878 /// .mount("/", routes![hello])
879 /// .mount("/hi", routes![hello]);
880 ///
881 /// assert_eq!(rocket.routes().count(), 2);
882 /// assert!(rocket.routes().any(|r| r.uri == "/hello"));
883 /// assert!(rocket.routes().any(|r| r.uri == "/hi/hello"));
884 /// ```
885 pub fn routes(&self) -> impl Iterator<Item = &Route> {
886 match self.0.as_ref() {
887 StateRef::Build(p) => Either::Left(p.routes.iter()),
888 StateRef::Ignite(p) => Either::Right(p.router.routes.iter()),
889 StateRef::Orbit(p) => Either::Right(p.router.routes.iter()),
890 }
891 }
892
893 /// Returns an iterator over all of the catchers registered on this instance
894 /// of Rocket. The order is unspecified.
895 ///
896 /// # Example
897 ///
898 /// ```rust
899 /// # extern crate rocket_community as rocket;
900 /// # use rocket::*;
901 /// use rocket::Rocket;
902 /// use rocket::fairing::AdHoc;
903 ///
904 /// #[catch(404)] fn not_found() -> &'static str { "Nothing here, sorry!" }
905 /// #[catch(500)] fn just_500() -> &'static str { "Whoops!?" }
906 /// #[catch(default)] fn some_default() -> &'static str { "Everything else." }
907 ///
908 /// let rocket = rocket::build()
909 /// .register("/foo", catchers![not_found])
910 /// .register("/", catchers![just_500, some_default]);
911 ///
912 /// assert_eq!(rocket.catchers().count(), 3);
913 /// assert!(rocket.catchers().any(|c| c.code == Some(404) && c.base() == "/foo"));
914 /// assert!(rocket.catchers().any(|c| c.code == Some(500) && c.base() == "/"));
915 /// assert!(rocket.catchers().any(|c| c.code == None && c.base() == "/"));
916 /// ```
917 pub fn catchers(&self) -> impl Iterator<Item = &Catcher> {
918 match self.0.as_ref() {
919 StateRef::Build(p) => Either::Left(p.catchers.iter()),
920 StateRef::Ignite(p) => Either::Right(p.router.catchers.iter()),
921 StateRef::Orbit(p) => Either::Right(p.router.catchers.iter()),
922 }
923 }
924
925 /// Returns `Some` of the managed state value for the type `T` if it is
926 /// being managed by `self`. Otherwise, returns `None`.
927 ///
928 /// # Example
929 ///
930 /// ```rust
931 /// # extern crate rocket_community as rocket;
932 /// #[derive(PartialEq, Debug)]
933 /// struct MyState(&'static str);
934 ///
935 /// let rocket = rocket::build().manage(MyState("hello!"));
936 /// assert_eq!(rocket.state::<MyState>().unwrap(), &MyState("hello!"));
937 /// ```
938 pub fn state<T: Send + Sync + 'static>(&self) -> Option<&T> {
939 match self.0.as_ref() {
940 StateRef::Build(p) => p.state.try_get(),
941 StateRef::Ignite(p) => p.state.try_get(),
942 StateRef::Orbit(p) => p.state.try_get(),
943 }
944 }
945
946 /// Returns a reference to the first fairing of type `F` if it is attached.
947 /// Otherwise, returns `None`.
948 ///
949 /// To retrieve a _mutable_ reference to fairing `F`, use
950 /// [`Rocket::fairing_mut()`] instead.
951 ///
952 /// # Example
953 ///
954 /// ```rust
955 /// # extern crate rocket_community as rocket;
956 /// # use rocket::{Rocket, Request, Data, Response, Build, Orbit};
957 /// # use rocket::fairing::{self, Fairing, Info, Kind};
958 /// #
959 /// # #[rocket::async_trait]
960 /// # impl Fairing for MyFairing {
961 /// # fn info(&self) -> Info {
962 /// # Info { name: "", kind: Kind::Ignite }
963 /// # }
964 /// # }
965 /// #
966 /// # #[rocket::async_trait]
967 /// # impl Fairing for MySingletonFairing {
968 /// # fn info(&self) -> Info {
969 /// # Info { name: "", kind: Kind::Ignite | Kind::Singleton }
970 /// # }
971 /// # }
972 /// // A regular, non-singleton fairing.
973 /// struct MyFairing(&'static str);
974 ///
975 /// // A singleton fairing.
976 /// struct MySingletonFairing(&'static str);
977 ///
978 /// // fairing is not attached, returns `None`
979 /// let rocket = rocket::build();
980 /// assert!(rocket.fairing::<MyFairing>().is_none());
981 /// assert!(rocket.fairing::<MySingletonFairing>().is_none());
982 ///
983 /// // attach fairing, now returns `Some`
984 /// let rocket = rocket.attach(MyFairing("some state"));
985 /// assert!(rocket.fairing::<MyFairing>().is_some());
986 /// assert_eq!(rocket.fairing::<MyFairing>().unwrap().0, "some state");
987 ///
988 /// // it returns the first fairing of a given type only
989 /// let rocket = rocket.attach(MyFairing("other state"));
990 /// assert_eq!(rocket.fairing::<MyFairing>().unwrap().0, "some state");
991 ///
992 /// // attach fairing, now returns `Some`
993 /// let rocket = rocket.attach(MySingletonFairing("first"));
994 /// assert_eq!(rocket.fairing::<MySingletonFairing>().unwrap().0, "first");
995 ///
996 /// // recall that new singletons replace existing attached singletons
997 /// let rocket = rocket.attach(MySingletonFairing("second"));
998 /// assert_eq!(rocket.fairing::<MySingletonFairing>().unwrap().0, "second");
999 /// ```
1000 pub fn fairing<F: Fairing>(&self) -> Option<&F> {
1001 match self.0.as_ref() {
1002 StateRef::Build(p) => p.fairings.filter::<F>().next(),
1003 StateRef::Ignite(p) => p.fairings.filter::<F>().next(),
1004 StateRef::Orbit(p) => p.fairings.filter::<F>().next(),
1005 }
1006 }
1007
1008 /// Returns an iterator over all attached fairings of type `F`, if any.
1009 ///
1010 /// # Example
1011 ///
1012 /// ```rust
1013 /// # extern crate rocket_community as rocket;
1014 /// # use rocket::{Rocket, Request, Data, Response, Build, Orbit};
1015 /// # use rocket::fairing::{self, Fairing, Info, Kind};
1016 /// #
1017 /// # #[rocket::async_trait]
1018 /// # impl Fairing for MyFairing {
1019 /// # fn info(&self) -> Info {
1020 /// # Info { name: "", kind: Kind::Ignite }
1021 /// # }
1022 /// # }
1023 /// #
1024 /// # #[rocket::async_trait]
1025 /// # impl Fairing for MySingletonFairing {
1026 /// # fn info(&self) -> Info {
1027 /// # Info { name: "", kind: Kind::Ignite | Kind::Singleton }
1028 /// # }
1029 /// # }
1030 /// // A regular, non-singleton fairing.
1031 /// struct MyFairing(&'static str);
1032 ///
1033 /// // A singleton fairing.
1034 /// struct MySingletonFairing(&'static str);
1035 ///
1036 /// let rocket = rocket::build();
1037 /// assert_eq!(rocket.fairings::<MyFairing>().count(), 0);
1038 /// assert_eq!(rocket.fairings::<MySingletonFairing>().count(), 0);
1039 ///
1040 /// let rocket = rocket.attach(MyFairing("some state"))
1041 /// .attach(MySingletonFairing("first"))
1042 /// .attach(MySingletonFairing("second"))
1043 /// .attach(MyFairing("other state"))
1044 /// .attach(MySingletonFairing("third"));
1045 ///
1046 /// let my_fairings: Vec<_> = rocket.fairings::<MyFairing>().collect();
1047 /// assert_eq!(my_fairings.len(), 2);
1048 /// assert_eq!(my_fairings[0].0, "some state");
1049 /// assert_eq!(my_fairings[1].0, "other state");
1050 ///
1051 /// let my_singleton: Vec<_> = rocket.fairings::<MySingletonFairing>().collect();
1052 /// assert_eq!(my_singleton.len(), 1);
1053 /// assert_eq!(my_singleton[0].0, "third");
1054 /// ```
1055 pub fn fairings<F: Fairing>(&self) -> impl Iterator<Item = &F> {
1056 match self.0.as_ref() {
1057 StateRef::Build(p) => Either::Left(p.fairings.filter::<F>()),
1058 StateRef::Ignite(p) => Either::Right(p.fairings.filter::<F>()),
1059 StateRef::Orbit(p) => Either::Right(p.fairings.filter::<F>()),
1060 }
1061 }
1062
1063 /// Returns a mutable reference to the first fairing of type `F` if it is
1064 /// attached. Otherwise, returns `None`.
1065 ///
1066 /// # Example
1067 ///
1068 /// ```rust
1069 /// # extern crate rocket_community as rocket;
1070 /// # use rocket::{Rocket, Request, Data, Response, Build, Orbit};
1071 /// # use rocket::fairing::{self, Fairing, Info, Kind};
1072 /// #
1073 /// # #[rocket::async_trait]
1074 /// # impl Fairing for MyFairing {
1075 /// # fn info(&self) -> Info {
1076 /// # Info { name: "", kind: Kind::Ignite }
1077 /// # }
1078 /// # }
1079 /// // A regular, non-singleton fairing.
1080 /// struct MyFairing(&'static str);
1081 ///
1082 /// // fairing is not attached, returns `None`
1083 /// let mut rocket = rocket::build();
1084 /// assert!(rocket.fairing_mut::<MyFairing>().is_none());
1085 ///
1086 /// // attach fairing, now returns `Some`
1087 /// let mut rocket = rocket.attach(MyFairing("some state"));
1088 /// assert!(rocket.fairing_mut::<MyFairing>().is_some());
1089 /// assert_eq!(rocket.fairing_mut::<MyFairing>().unwrap().0, "some state");
1090 ///
1091 /// // we can modify the fairing
1092 /// rocket.fairing_mut::<MyFairing>().unwrap().0 = "other state";
1093 /// assert_eq!(rocket.fairing_mut::<MyFairing>().unwrap().0, "other state");
1094 ///
1095 /// // it returns the first fairing of a given type only
1096 /// let mut rocket = rocket.attach(MyFairing("yet more state"));
1097 /// assert_eq!(rocket.fairing_mut::<MyFairing>().unwrap().0, "other state");
1098 /// ```
1099 pub fn fairing_mut<F: Fairing>(&mut self) -> Option<&mut F> {
1100 match self.0.as_mut() {
1101 StateRefMut::Build(p) => p.fairings.filter_mut::<F>().next(),
1102 StateRefMut::Ignite(p) => p.fairings.filter_mut::<F>().next(),
1103 StateRefMut::Orbit(p) => p.fairings.filter_mut::<F>().next(),
1104 }
1105 }
1106
1107 /// Returns an iterator of mutable references to all attached fairings of
1108 /// type `F`, if any.
1109 ///
1110 /// # Example
1111 ///
1112 /// ```rust
1113 /// # extern crate rocket_community as rocket;
1114 /// # use rocket::{Rocket, Request, Data, Response, Build, Orbit};
1115 /// # use rocket::fairing::{self, Fairing, Info, Kind};
1116 /// #
1117 /// # #[rocket::async_trait]
1118 /// # impl Fairing for MyFairing {
1119 /// # fn info(&self) -> Info {
1120 /// # Info { name: "", kind: Kind::Ignite }
1121 /// # }
1122 /// # }
1123 /// // A regular, non-singleton fairing.
1124 /// struct MyFairing(&'static str);
1125 ///
1126 /// let mut rocket = rocket::build()
1127 /// .attach(MyFairing("some state"))
1128 /// .attach(MyFairing("other state"))
1129 /// .attach(MyFairing("yet more state"));
1130 ///
1131 /// let mut fairings: Vec<_> = rocket.fairings_mut::<MyFairing>().collect();
1132 /// assert_eq!(fairings.len(), 3);
1133 /// assert_eq!(fairings[0].0, "some state");
1134 /// assert_eq!(fairings[1].0, "other state");
1135 /// assert_eq!(fairings[2].0, "yet more state");
1136 ///
1137 /// // we can modify the fairings
1138 /// fairings[1].0 = "modified state";
1139 ///
1140 /// let fairings: Vec<_> = rocket.fairings::<MyFairing>().collect();
1141 /// assert_eq!(fairings.len(), 3);
1142 /// assert_eq!(fairings[0].0, "some state");
1143 /// assert_eq!(fairings[1].0, "modified state");
1144 /// assert_eq!(fairings[2].0, "yet more state");
1145 /// ```
1146 pub fn fairings_mut<F: Fairing>(&mut self) -> impl Iterator<Item = &mut F> {
1147 match self.0.as_mut() {
1148 StateRefMut::Build(p) => Either::Left(p.fairings.filter_mut::<F>()),
1149 StateRefMut::Ignite(p) => Either::Right(p.fairings.filter_mut::<F>()),
1150 StateRefMut::Orbit(p) => Either::Right(p.fairings.filter_mut::<F>()),
1151 }
1152 }
1153
1154 /// Returns the figment derived from the configuration provider set for
1155 /// `self`. To extract a typed config, prefer to use
1156 /// [`AdHoc::config()`](crate::fairing::AdHoc::config()).
1157 ///
1158 /// Note; A [`Figment`] generated from the current `provider` can _always_
1159 /// be retrieved via this method. However, because the provider can be
1160 /// changed at any point prior to ignition, a [`Config`] can only be
1161 /// retrieved in the ignite or orbit phases, or by manually extracting one
1162 /// from a particular figment.
1163 ///
1164 /// # Example
1165 ///
1166 /// ```rust
1167 /// # extern crate rocket_community as rocket;
1168 /// let rocket = rocket::build();
1169 /// let figment = rocket.figment();
1170 /// ```
1171 pub fn figment(&self) -> &Figment {
1172 match self.0.as_ref() {
1173 StateRef::Build(p) => &p.figment,
1174 StateRef::Ignite(p) => &p.figment,
1175 StateRef::Orbit(p) => &p.figment,
1176 }
1177 }
1178
1179 async fn into_ignite(self) -> Result<Rocket<Ignite>, Error> {
1180 match self.0.into_state() {
1181 State::Build(s) => Rocket::from(s).ignite().await,
1182 State::Ignite(s) => Ok(Rocket::from(s)),
1183 State::Orbit(s) => Ok(Rocket::from(s).deorbit()),
1184 }
1185 }
1186
1187 pub(crate) async fn local_launch(self, e: Endpoint) -> Result<Rocket<Orbit>, Error> {
1188 Ok(self.into_ignite().await?._local_launch(e).await)
1189 }
1190
1191 /// Returns a `Future` that transitions this instance of `Rocket` from any
1192 /// phase into the _orbit_ phase. When `await`ed, the future drives the
1193 /// server forward, listening for and dispatching requests to mounted routes
1194 /// and catchers.
1195 ///
1196 /// In addition to all of the processes that occur during
1197 /// [ignition](Rocket::ignite()), a successful launch results in _liftoff_
1198 /// fairings being executed _after_ binding to any respective network
1199 /// interfaces but before serving the first request. Liftoff fairings are
1200 /// run concurrently; resolution of all fairings is `await`ed before
1201 /// resuming request serving.
1202 ///
1203 /// The `Future` resolves as an `Err` if any of the following occur:
1204 ///
1205 /// * there is an error igniting; see [`Rocket::ignite()`].
1206 /// * there is an I/O error starting the server.
1207 /// * an unrecoverable, system-level error occurs while running.
1208 ///
1209 /// The `Future` resolves as an `Ok` if any of the following occur:
1210 ///
1211 /// * graceful shutdown via [`Shutdown::notify()`] completes.
1212 ///
1213 /// The returned value on `Ok(())` is previously running instance.
1214 ///
1215 /// The `Future` does not resolve otherwise.
1216 ///
1217 /// # Error
1218 ///
1219 /// If there is a problem starting the application or the application fails
1220 /// unexpectedly while running, an [`Error`] is returned. Note that a value
1221 /// of type `Error` panics if dropped without first being inspected. See the
1222 /// [`Error`] documentation for more information.
1223 ///
1224 /// # Example
1225 ///
1226 /// ```rust,no_run
1227 /// # extern crate rocket_community as rocket;
1228 /// #[rocket::main]
1229 /// async fn main() {
1230 /// let result = rocket::build().launch().await;
1231 ///
1232 /// // this is reachable only after `Shutdown::notify()` or `Ctrl+C`.
1233 /// println!("Rocket: deorbit.");
1234 /// }
1235 /// ```
1236 pub async fn launch(self) -> Result<Rocket<Ignite>, Error> {
1237 self.launch_with::<DefaultListener>().await
1238 }
1239
1240 pub async fn launch_with<B: Bind>(self) -> Result<Rocket<Ignite>, Error> {
1241 let rocket = self.into_ignite().await?;
1242 let bind_endpoint = B::bind_endpoint(&rocket).ok();
1243 let listener: B = B::bind(&rocket)
1244 .await
1245 .map_err(|e| ErrorKind::Bind(bind_endpoint, Box::new(e)))?;
1246
1247 let any: Box<dyn Any + Send + Sync> = Box::new(listener);
1248 match any.downcast::<DefaultListener>() {
1249 Ok(listener) => {
1250 let listener = *listener;
1251 crate::util::for_both!(listener, listener => {
1252 crate::util::for_both!(listener, listener => {
1253 rocket._launch(listener).await
1254 })
1255 })
1256 }
1257 Err(any) => {
1258 let listener = *any.downcast::<B>().unwrap();
1259 rocket._launch(listener).await
1260 }
1261 }
1262 }
1263
1264 pub async fn try_launch_on<L, F, E>(self, listener: F) -> Result<Rocket<Ignite>, Error>
1265 where
1266 L: Listener + 'static,
1267 F: Future<Output = Result<L, E>>,
1268 E: std::error::Error + Send + 'static,
1269 {
1270 let listener = listener
1271 .map_err(|e| ErrorKind::Bind(None, Box::new(e)))
1272 .await?;
1273 self.into_ignite().await?._launch(listener).await
1274 }
1275
1276 pub async fn launch_on<L>(self, listener: L) -> Result<Rocket<Ignite>, Error>
1277 where
1278 L: Listener + 'static,
1279 {
1280 self.into_ignite().await?._launch(listener).await
1281 }
1282}
1283
1284#[doc(hidden)]
1285impl<P: Phase> Deref for Rocket<P> {
1286 type Target = P::State;
1287
1288 fn deref(&self) -> &Self::Target {
1289 &self.0
1290 }
1291}
1292
1293#[doc(hidden)]
1294impl<P: Phase> DerefMut for Rocket<P> {
1295 fn deref_mut(&mut self) -> &mut Self::Target {
1296 &mut self.0
1297 }
1298}
1299
1300impl<P: Phase> fmt::Debug for Rocket<P> {
1301 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1302 self.0.fmt(f)
1303 }
1304}