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}