This commit implements a workaround for an [issue within rustc]. The
problem showed itself when using e.g. a `Vec<&str>` argument in an async
route handler (but not `&str`), which resulted in a "implementation of
`FromForm` is not general enough" error. The workaround itself works by
gathering all invocations of `FromForm`'s methods inside a block without
any `.await` points [ref].
[issue within rustc]: https://github.com/rust-lang/rust/issues/69663
[ref]: https://github.com/rust-lang/rust/issues/57478#issuecomment-501186084
As 'FromForm' doesn't provide access to the raw, undecoded string,
'MsgPack' cannot implement 'FromForm::from_value()'. This means that it
is not presently possible to parse a MessagePack form from a query
string. As such, the 'UriDisplay<Query>' implementation was removed.
The 'UriDisplay<Query>' for JSON was fixed such that a round-trip of a
'Json<T>' as a form works as expected.
The 'FromFrom' derive now allows type generics in all positions using
the same automatic discovery technique as with 'Responder'. (In fact,
the technique was created for this derive.) Furthermore, 'FromForm' can
now be derived for unit structs.
Also adds a new 'try_with' form field validator.
Resolves#1695.
This commit presents and applies a new technique for bounding type
generics in derives. In short, for a generic `T` used in a field type of
`Field<T>`, where an eventual bound of `Responder` required, the derive
generates a bound of `Field<T>: Responder`. This removes the need for
any manually provided bounds while simultaneously allowing more
structures to typecheck. For example, generics in header components are
now fully supported.
This allows responses to be sent to the client even when data is only
partially read, significantly improving the experience for the client
from one with a "connection closed" error to one with a proper response.
The consequence is a lifetime in 'Data'.
Though other non-lifetime-introducing solutions exist, the introduction
of a lifetime to 'Data' is a longstanding desire as it prevents
smuggling 'Data' into a longer-lived context. Use of 'Data' in that
context was unspecified with various runtime consequences. The addition
of a lifetime bound by the request prevents this error statically.
In summary, the changes are:
* Clients receive responses even when data isn't fully read.
* 'Data' becomes 'Data<'r>'. 'FromData' changes accordingly.
* Route 'Outcome's are strictly tied to the request lifetime.
Tangentially, the invalid length form field validation error message has
improved to format length in byte units if it exceeds 1024.
This resolves syntax ambiguity issues with public typed-stream macros.
Prior to this commit, greedy single-token matching by macro-rules macros
would result in certain tokens at the beginning of the macro input, such
as 'for', inadvertently triggering a '$ty' matching case resulting in
incorrect expansion.
This commit entirely rewrites Rocket's URI parsing routines and
overhauls the 'uri!' macro resolving all known issues and removing any
potential limitations for compile-time URI creation. This commit:
* Introduces a new 'Reference' URI variant for URI-references.
* Modifies 'Redirect' to accept 'TryFrom<Reference>'.
* Introduces a new 'Asterisk' URI variant for parity.
* Allows creation of any URI type from a string literal via 'uri!'.
* Enables dynamic/static prefixing/suffixing of route URIs in 'uri!'.
* Unifies 'Segments' and 'QuerySegments' into one generic 'Segments'.
* Consolidates URI formatting types/traits into a 'uri::fmt' module.
* Makes APIs more symmetric across URI types.
It also includes the following less-relevant changes:
* Implements 'FromParam' for a single-segment 'PathBuf'.
* Adds 'FileName::is_safe()'.
* No longer reparses upstream request URIs.
Resolves#842.
Resolves#853.
Resolves#998.
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>'.
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.
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.
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.
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`.
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.
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 changes core routing so that '<path..>' in a route URI matches zero
or more segments. Previously, '<path..>' matched _1_ or more.
* Routes '$a' and '$b/<p..>' collide if $a and $b previously collided.
* For example, '/' now collides with '/<p..>'.
* Request '$a' matches route '$b/<p..>' if $a previously matched $b.
* For example, request '/' matches route '/<p..>'.
Resolves#985.
This commit completely revamps the way that codegen handles route URI
"parameters". The changes are largely internal. In summary, codegen code
is better organized, better written, and less subject to error.
There are three breaking changes:
* `path` is now `uri` in `route` attribute: `#[route(GET, path = "..")]`
becomes `#[route(GET, uri = "..")]`.
* the order of execution for path and query guards relative to
each-other is now unspecified
* URI normalization now normalizes the query part as well.
Several error messages were improved. A couple of bugs were fixed:
* Prior to this commit, Rocket would optimistically try to parse every
segment of a URI as an ident, in case one was needed in the future.
A bug in rustc results in codegen "panicking" if the segment
couldn't _lex_ as an ident. This panic didn't manifest until far
after expansion, unfortunately. This wasn't a problem before as we
only allowed ident-like segments (ASCII), but now that we allow any
UTF-8, the bug surfaced. This was fixed by never attempting to parse
non-idents as idents.
* Prior to this commit, it was impossible to generate typed URIs for
paths that ignored path parameters via the recently added syntax
`<_>`: the macro would panic. This was fixed by, well, handling
these ignored parameters.
Some minor additions:
* Added `RawStr::find()`, expanding its `Pattern`-based API.
* Added an internal mechanism to dynamically determine if a `UriPart`
is `Path` or `Query`.