This has the following positive effects:
1) The lifetime retrieved through 'Deref' is now long-lived.
2) An '&State<T>` can be created via an '&T'.
3) '&State<T>' is shorter to type than 'State<'_, T>'.
The crux of the implementation is as follows:
* Configurable ctrl-c, signals that trigger a graceful shutdown.
* Configurable grace period before forced I/O termination.
* Programatic triggering via an application-wide method.
* A future (`Shutdown`) that resolves only when shutdown is requested.
Resolves#180.
This is a breaking change for many consumers of the 'Response' and all
consumers of the 'Body' API. The summary of breaking changes is:
* 'Response::body()', 'Response::body_mut()' are infallible.
* A 'Body' can represent an empty body in more cases.
* 'ResponseBuilder' is now simply 'Builder'.
* Direct body read methods on 'Response' were removed in favor of
chaining through 'body_mut()': 'r.body_mut().to_string()'.
* Notion of a 'chunked_body' was removed as it was inaccurate.
* Maximum chunk size can be set on any body.
* 'Response' no longer implements 'Responder'.
A few bugs were fixed in the process. Specifically, 'Body' will emit an
accurate size even for bodies that are partially read, and the size of
seek-determined bodies is emitted on HEAD request where it wasn't
before. Specifics on transport were clarified, and 'Body' docs greatly
improved as a result.
This removes the export of each of these macros from the root, limiting
their export-scope to their respective module. This is accomplished
using a new internal macro, 'export!', which does some "magic" to work
around rustdoc deficiencies.
Changes codegen to use an instance method on the route proxy struct
rather than implementing a trait on the proxy struct. This helps rustc
identify unused routes.
Resolves#1598.
This commit includes changes that improve how and what Rocket logs
automatically. Rocket now logs:
* All guard errors, indicating the failing guard kind and type.
* A warning when a 'TempFile' is used as a data guard for a request
that specifies a 'form' Content-Type.
* Only the top/sub of a request's format.
This commit makes the following breaking changes:
* '<T as FromData>::Error' must implement 'Debug'.
Furthermore, this commit restores the previous behavior of always
logging launch info. It further restores the unspecified behavior of
modifying logging state only when the set logger is Rocket's logger.
Sentinels resolve a long-standing usability and functional correctness
issue in Rocket: starting an application with guards and/or responders
that depend on state that isn't available. The canonical example is the
'State' guard. Prior to this commit, an application with routes that
queried unmanaged state via 'State' would fail at runtime. With this
commit, the application refuses to launch with a detailed error message.
The 'Sentinel' docs explains it as:
A sentinel, automatically run on ignition, can trigger a launch
abort should an instance fail to meet arbitrary conditions. Every
type that appears in a mounted route's type signature is eligible to
be a sentinel. Of these, those that implement 'Sentinel' have their
'abort()' method invoked automatically, immediately after ignition,
once for each unique type. Sentinels inspect the finalized instance
of 'Rocket' and can trigger a launch abort by returning 'true'.
The following types are now sentinels:
* 'contrib::databases::Connection' (any '#[database]' type)
* 'contrib::templates::Metadata'
* 'contrib::templates::Template'
* 'core::State'
The following are "specialized" sentinels, which allow sentinel
discovery even through type aliases:
* 'Option<T>', 'Debug<T>' if 'T: Sentinel'
* 'Result<T, E>', 'Either<T, E>' if 'T: Sentinel', 'E: Sentinel'
Closes#464.
The core 'Rocket' type is parameterized: 'Rocket<P: Phase>', where
'Phase' is a newly introduced, sealed marker trait. The trait is
implemented by three new marker types representing the three launch
phases: 'Build', 'Ignite', and 'Orbit'. Progression through these three
phases, in order, is enforced, as are the invariants guaranteed by each
phase. In particular, an instance of 'Rocket' is guaranteed to be in its
final configuration after the 'Build' phase and represent a running
local or public server in the 'Orbit' phase. The 'Ignite' phase serves
as an intermediate, enabling inspection of a finalized but stationary
instance. Transition between phases validates the invariants required
by the transition.
All APIs have been adjusted appropriately, requiring either an instance
of 'Rocket' in a particular phase ('Rocket<Build>', 'Rocket<Ignite>', or
'Rocket<Orbit>') or operating generically on a 'Rocket<P>'.
Documentation is also updated and substantially improved to mention
required and guaranteed invariants.
Additionally, this commit makes the following relevant changes:
* 'Rocket::ignite()' is now a public interface.
* 'Rocket::{build,custom}' methods can no longer panic.
* 'Launch' fairings are now 'ignite' fairings.
* 'Liftoff' fairings are always run, even in local mode.
* All 'ignite' fairings run concurrently at ignition.
* Launch logging occurs on launch, not any point prior.
* Launch log messages have improved formatting.
* A new launch error kind, 'Config', was added.
* A 'fairing::Result' type alias was introduced.
* 'Shutdown::shutdown()' is now 'Shutdown::notify()'.
Some internal changes were also introduced:
* Fairing 'Info' name for 'Templates' is now 'Templating'.
* Shutdown is implemented using 'tokio::sync::Notify'.
* 'Client::debug()' is used nearly universally in tests.
Resolves#1154.
Resolves#1136.
...because loading up a Rocket while it's ignited is a bad idea.
More seriously, because 'Rocket.ignite()' will become an "execute
everything up to here" method.
The new examples directory...
* Contains a `README.md` explaining each example.
* Consolidates examples into more complete chunks.
* Is just better.
Resolves#1447.
The options set WAL, a 1s busy timeout, and enables foreign keys.
This also adds a focused 'databases::Config::figment()', used to
retrieve a focused figment for a given config.
In particular, 'FromFormField' and 'UriDisplayQuery' now allow any
number of form 'field' attributes. For the former, multiple 'value's are
allowed, all of which are used to match against incoming fields - any
match wins. For the latter, multiple 'name' and 'value's are allowed;
the first of each is used to render the query value.
Additionally, 'UriDisplayQuery' can now be derived for C-like enums.
This brings the derive to parity with 'FromFormValue' and allows their
unified application on C-like enums.
Resolves#843.
This is now consistent with the serialization of 'Flash' and better
illustrates the purpose of the late 'name' property.
Additionally, take 'Into<String>' instead of 'AsRef<str>' so we only
allocate when necessary.
Launch fairings are now fallible and take the place of attach fairings,
but they are only run, as the name implies, at launch time.
This is is a fundamental shift from eager execution of set-up routines,
including the now defunct attach fairings, to lazy execution,
precipitated by the transition to `async`. The previous functionality,
while simple, caused grave issues:
1. A instance of 'Rocket' with async attach fairings requires an async
runtime to be constructed.
2. The instance is accessible in non-async contexts.
3. The async attach fairings have no runtime in which to be run.
Here's an example:
```rust
let rocket = rocket::ignite()
.attach(AttachFairing::from(|rocket| async {
Ok(rocket.manage(load_from_network::<T>().await))
}));
let state = rocket.state::<T>();
```
This had no real meaning previously yet was accepted by running the
attach fairing future in an isolated runtime. In isolation, this causes
no issue, but when attach fairing futures share reactor state with other
futures in Rocket, panics ensue.
The new Rocket application lifecycle is this:
* Build - A Rocket instance is constructed. No fairings are run.
* Ignition - All launch fairings are run.
* Liftoff - If all launch fairings succeeded, the server is started.
New 'liftoff' fairings are run in this third phase.
Catchers can now be scoped to paths, with preference given to the
longest-prefix, then the status code. This a breaking change for all
applications that register catchers:
* `Rocket::register()` takes a base path to scope catchers under.
- The previous behavior is recovered with `::register("/", ...)`.
* Catchers now fallibly, instead of silently, collide.
* `ErrorKind::Collision` is now `ErrorKind::Collisions`.
Related changes:
* `Origin` implements `TryFrom<String>`, `TryFrom<&str>`.
* All URI variants implement `TryFrom<Uri>`.
* Added `Segments::prefix_of()`.
* `Rocket::mount()` takes a `TryInto<Origin<'_>>` instead of `&str`
for the base mount point.
* Extended `errors` example with scoped catchers.
* Added scoped sections to catchers guide.
Internal changes:
* Moved router code to `router/router.rs`.
The new benchmarks use routes from real-world project. This is much more
realistic than the previous benchmarks.
The new benchmarks use `criterion` and exist in their own Cargo project.
This surfaced a dormant concurrency related issue. Prior to this commit,
the router used `routed_segments()` to retrieve the path segments of the
request. This was okay as there was no route in the request, and matched
segments were retrieved eagerly.
This commit makes segment matching lazy, so no matching occurs if
unnecessary. Between two matches, a `route` is atomically set of
`Request`. This is now visible in `routed_segments()`, which should not
have considered the current route in the first place. This was fixed.
While offering some utility, the lifetime did not carry its weight, and
in practice offered no further ability to borrow. This greatly
simplifies request guard implementations.
This prevents printing a secret key warning if a secret key was
generated, as is done by Rocket itself. This does not change any
behaviors in non-debug profiles.
Prior to this commit, it was not possible to test Rocket crates in
production mode without setting a global secret key or bypassing secret
key checking - the testing script did the latter. The consequence is
that it became impossible to test secret key related failures because
the tests passed regardless.
This commit undoes this. As a consequence, all tests are now aware of
the difference between debug and release configurations, the latter of
which validates 'secret_key' by default. New 'Client::debug()' and
'Client::debug_with()' simplify creating an instance of 'Client' with
configuration in debug mode to avoid undesired test failures.
The summary of changes in this commit are:
* Config 'secret_key' success and failure are now tested.
* 'secret_key' validation was moved to pre-launch from 'Config:from()'.
* 'Config::from()' only extracts the config.
* Added 'Config::try_from()' for non-panicking extraction.
* 'Config' now knows the profile it was extracted from.
* The 'Config' provider sets a profile of 'Config.profile'.
* 'Rocket', 'Client', 'Fairings', implement 'Debug'.
* 'fairing::Info' implements 'Copy', 'Clone'.
* 'Fairings' keeps track of, logs attach fairings.
* 'Rocket::reconfigure()' was added to allow modifying a config.
Internally, the testing script was refactored to properly test the
codebase with the new changes. In particular, it no longer sets a rustc
'cfg' to avoid secret-key checking.
Resolves#1543.
Fixes#1564.
This commit makes the `Config.secret_key` conditionally compile on the
`secrets` feature. The net effect is simplified internal code, fewer
corner-cases, and easier to write tests.
This commit removes the `Provider::profile()` implementation of
`Config`. This means that the `Config` provider no longer sets a
profile, a likely confusing behavior. The `Config::figment()` continues
to function as before.
This changes core routing so that panics in all handlers are handled by
emitting a long message explaining that panics are bad and invoking the
500 error catcher. If the 500 error catcher fails, Rocket's default 500
catcher is used.