Commit Graph

114 Commits

Author SHA1 Message Date
Sergio Benitez 162fafa0f1 Update UI tests for nightly. 2022-11-18 19:30:35 -08:00
Sergio Benitez 7e913eb8ac Report as many form errors as possible. 2022-11-12 04:11:18 -08:00
Kevin Wang f7e703bc5e Fix 'Limits' deserialization.
Fixes #2268.
2022-08-01 13:11:02 -07:00
pennae 7275df9fdf Make data guards eligible to be sentinels.
Prior to this commit, data guards were not being considered as eligible
to be sentinels. This commit resolves that.
2022-06-23 16:15:11 -07:00
Sergio Benitez 7908dc43ca Introduce shutdown fairings.
Also adds 'Client::terminate()' to run graceful shutdown in testing.

Resolves #1707.
2022-05-07 06:12:32 -05:00
Sergio Benitez ee4aa81847 Allow '[' and ']' in URI paths.
This is strictly noncompliant and they should be encoded, but browsers
routinely send them unencoded, so we allow them to avoid trouble.
2022-05-04 09:44:24 -07:00
Sergio Benitez 82cd53de36 Add 'must_use' to 'Rocket'.
Closes #2146.
2022-04-19 13:03:58 -07:00
Sergio Benitez 1b37d571c2 Rework 'local_cache!' so it returns unique refs.
Fixes #1987.
2022-04-18 18:12:54 -07:00
arlecchino 1ba41b3990 Remove 'CookieJar::get_private_pending()'.
This commit removes the 'CookieJar::get_private_pending()' method in
favor of the already existing and correct 'CookieJar::get_pending()'
method. Previously, the 'CookieJar::get_private_pending()' method
attempted to decrypt the value of a pending cookie, which in reality is
plaintext, thus failing. Because the pending value is plaintext, the
'CookieJar::get_pending()' method suffices.

Documentation has been updated to refer to 'CookieJar::get_pending()'.

Fixes #2063.
2022-02-17 11:04:30 -08:00
Sergio Benitez 0ba5aac53e Update codebase for latest nightly and stable. 2022-02-16 10:08:55 -08:00
Sergio Benitez cc0621626b Prefix 'content' responder names with 'Raw'.
The primary aim of this commit is to reduce confusion between
'content::Json' and 'rocket::serde::json::Json' be renaming the former
to 'content::RawJson'. The complete changes in this PR are:

  * All responders in the 'content' module are prefixed with 'Raw'.
  * The 'content::Custom' responder was removed entirely.
  * The 'Plain' responder is now 'RawText'.
  * The 'content' API docs point to the 'serde' responders.
  * The docs and examples were updated accordingly.
2021-07-20 02:09:11 -07:00
Sergio Benitez 614f8ab46c Condition TLS config types on 'tls' feature.
Previously, TLS, via 'Config::tls', was configurable even if the 'tls'
feature was disabled. This commit changes this so that the 'Config::tls'
field and TLS config structures are only available if 'tls' is enabled.
2021-07-05 13:46:37 -07:00
Sergio Benitez 3ec58c3ca2 Ensure launch occurs with minimal ciphersuites.
Co-authored-by: Abdullah Alyan <AbdullahAlyan@yahoo.com>
2021-06-29 11:27:54 -07:00
Sergio Benitez 686a0ed964 Fix wording in 'config' docs. 2021-06-26 17:11:53 -07:00
Sergio Benitez c3ee34e295 Drop sender to prevent async client read deadlock.
Fixes #1729.

Co-authored-by: Wesley Norris <repnop@outlook.com>
2021-06-25 09:27:36 -07:00
Sergio Benitez d2c2725689 Implement 'De(Serialize)' for 'Method'. 2021-06-09 17:07:26 -07:00
Sergio Benitez 128234d9a8 Allow customizing and removing 'Server' header. 2021-06-08 23:09:57 -07:00
Sergio Benitez 4c6562cd29 Drop 'Data' after sending a response, not before.
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.
2021-06-08 13:26:16 -07:00
Sergio Benitez 0d53e23bf6 Discover sentinels in known type macros.
Resolves #1657.
2021-06-03 19:31:30 -07:00
Sergio Benitez faaa9c9065 Fixup URI (de)serialization. 2021-05-24 12:16:03 -07:00
Matthew Pomes 1233518733 Implement (De)Serialize for all URI variants.
Closes #1593.
2021-05-24 12:15:52 -07:00
Sergio Benitez b1d05d20ac Graduate 'serve' into core as 'fs', 'FileServer'.
This completes the graduation of stable 'contrib' features to 'core'.

Closes #1107.
2021-05-22 11:15:56 -07:00
Sergio Benitez f6a7087c84 Graduate 'helmet' as 'shield' into core.
The 'SpaceHelmet' fairing is now called 'Shield'. It features the
following changes and improvements:

  * Headers which are now ignored by browsers are removed.
  * 'XssFilter' is no longer an on-by-default policy.
  * A new 'Permission' policy is introduced.
  * 'Shield' is attached to all 'Rocket' instances by default.
  * Default headers never allocate on 'Clone'.
  * Policy headers are rendered once and cached at start-up.
  * Improved use of typed URIs in policy types.
2021-05-22 11:01:00 -07:00
Sergio Benitez 267cb9396f Introduce 'Singleton' fairings.
A singleton fairing is guaranteed to be the only instance of its type at
launch time. If more than one instance of a singleton fairing is
attached, only the last instance is retained.
2021-05-22 11:01:00 -07:00
Sergio Benitez fa3e0334c1 Overhaul URI types, parsers, 'uri!' macro.
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.
2021-05-19 18:47:11 -07:00
Sergio Benitez d03a07b183 Retrieve managed state via a borrow: '&State<T>'.
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>'.
2021-05-11 08:58:16 -05:00
Sergio Benitez 63e6845386 Revamp 'Response', 'Body' types.
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.
2021-04-28 02:21:33 -07:00
Sergio Benitez 64e46b7107 Introduce sentinels: auto-discovered launch abort.
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.
2021-04-16 01:44:53 -07:00
Sergio Benitez 4f3511786c Introduce statically-enforced 'Rocket' phasing.
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.
2021-04-13 19:26:45 -07:00
Sergio Benitez 887b2aed87 Move catcher, route types into eponymous modules.
In the course, significantly improve their documentation.
2021-04-13 18:58:05 -07:00
Sergio Benitez c16105dc58 Impl 'DerefMut', 'inner_mut()' for 'LocalRequest'. 2021-04-13 17:40:22 -07:00
Sergio Benitez ad36b769bc Rename 'rocket::ignite()' to 'rocket::build()'.
...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.
2021-04-08 01:07:52 -07:00
Sergio Benitez 50c9e88cf9 Completely revamp, redo examples.
The new examples directory...

  * Contains a `README.md` explaining each example.
  * Consolidates examples into more complete chunks.
  * Is just better.

Resolves #1447.
2021-04-07 23:09:05 -07:00
Sergio Benitez 5931d6704b Split 'AdHoc::on_launch' into two by fallibility.
The new 'AdHoc::try_on_launch()' replaces the previous 'on_launch'. The
new 'on_launch' returns a 'Rocket' directly.
2021-04-07 23:09:05 -07:00
Sergio Benitez 8d28e845d9 Rename 'Flash' 'name', 'msg' to 'kind', 'message'.
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.
2021-04-07 23:09:05 -07:00
Sergio Benitez 0bdb6b7bc7 Remove 'attach' fairings. Add 'liftoff' fairings.
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.
2021-04-07 23:09:00 -07:00
Sergio Benitez 2893ce754d Introduce scoped catchers.
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`.
2021-03-28 13:57:33 -07:00
Sergio Benitez 2463637d51 Introduce 'RouteUri'.
Co-authored-by: Ben Sully <ben@bsull.io>
2021-03-19 03:49:54 -07:00
Sergio Benitez 304e65ac72 Catch panics that occur before future is returned.
In the course of resolving this issue, double-boxing of handlers was
discovered and removed.
2021-03-15 02:20:48 -07:00
Sergio Benitez 70b42e6f0e Remove second lifetime from 'FromRequest'.
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.
2021-03-14 19:57:59 -07:00
Sergio Benitez 4e06ee64aa Test 'secret_key' validation, now on pre-launch.
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.
2021-03-09 21:57:26 -08:00
Sergio Benitez 83ffe0f7bc Remove 'Config::profile()'. CFG 'secret_key' field.
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.
2021-03-09 21:40:53 -08:00
Jeb Rosen d778c2cb10 Drop embedded async 'Client' in async runtime. 2021-03-06 01:40:43 -08:00
Sergio Benitez 68b244ebdc Forward catcher, handler failure to 500 catcher.
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.
2021-03-06 01:39:31 -08:00
Jeb Rosen a0784b4b15 Catch and gracefully handle panics in routes and catchers. 2021-03-05 22:58:28 -08:00
Sergio Benitez 63a14525d8 UTF-8 routes. Forms revamp. Temp files. Capped.
So. Many. Changes.

This is an insane commit: simultaneously one of the best (because of all
the wonderful improvements!) and one of the worst (because it is just
massive) in the project's history.

Routing:
  * All UTF-8 characters are accepted everywhere in route paths. (#998)
  * `path` is now `uri` in `route` attribute: `#[route(GET, path = "..")]`
    becomes `#[route(GET, uri = "..")]`.

Forms Revamp
  * All form related types now reside in a new `form` module.
  * Multipart forms are supported. (resolves #106)
  * Collections are supported in forms and queries. (resolves #205)
  * Nested structures in forms and queries are supported. (resolves #313)
  * Form fields can be ad-hoc validated with `#[field(validate = expr)]`.
  * `FromFormValue` is now `FromFormField`, blanket implements `FromForm`.
  * Form field values are always percent-decoded apriori.

Temporary Files
  * A new `TempFile` data and form guard allows streaming data directly to a
    file which can then be persisted.
  * A new `temp_dir` config parameter specifies where to store `TempFile`.
  * The limits `file` and `file/$ext`, where `$ext` is the file extension,
    determines the data limit for a `TempFile`.

Capped
  * A new `Capped` type is used to indicate when data has been truncated due to
    incoming data limits. It allows checking whether data is complete or
    truncated.
  * `DataStream` methods return `Capped` types.
  * `DataStream` API has been revamped to account for `Capped` types.
  * Several `Capped<T>` types implement `FromData`, `FromForm`.
  * HTTP 413 (Payload Too Large) errors are now returned when data limits are
    exceeded. (resolves #972)

Hierarchical Limits
  * Data limits are now hierarchical, delimited with `/`. A limit of `a/b/c`
    falls back to `a/b` then `a`.

Core
  * `&RawStr` no longer implements `FromParam`.
  * `&str` implements `FromParam`, `FromData`, `FromForm`.
  * `FromTransformedData` was removed.
  * `FromData` gained a lifetime for use with request-local data.
  * The default error HTML is more compact.
  * `&Config` is a request guard.
  * The `DataStream` interface was entirely revamped.
  * `State` is only exported via `rocket::State`.
  * A `request::local_cache!()` macro was added for storing values in
    request-local cache without consideration for type uniqueness by using a
    locally generated anonymous type.
  * `Request::get_param()` is now `Request::param()`.
  * `Request::get_segments()` is now `Request::segments()`, takes a range.
  * `Request::get_query_value()` is now `Request::query_value()`, can parse any
    `FromForm` including sequences.
  * `std::io::Error` implements `Responder` like `Debug<std::io::Error>`.
  * `(Status, R)` where `R: Responder` implements `Responder` by overriding the
    `Status` of `R`.
  * The name of a route is printed first during route matching.
  * `FlashMessage` now only has one lifetime generic.

HTTP
  * `RawStr` implements `serde::{Serialize, Deserialize}`.
  * `RawStr` implements _many_ more methods, in particular, those related to the
    `Pattern` API.
  * `RawStr::from_str()` is now `RawStr::new()`.
  * `RawStr::url_decode()` and `RawStr::url_decode_lossy()` only allocate as
    necessary, return `Cow`.
  * `Status` implements `Default` with `Status::Ok`.
  * `Status` implements `PartialEq`, `Eq`, `Hash`, `PartialOrd`, `Ord`.
  * Authority and origin part of `Absolute` can be modified with new
    `Absolute::{with,set}_authority()`, `Absolute::{with,set}_origin()` methods.
  * `Origin::segments()` was removed in favor of methods split into query and
    path parts and into raw and decoded versions.
  * The `Segments` iterator is smarter, returns decoded `&str` items.
  * `Segments::into_path_buf()` is now `Segments::to_path_buf()`.
  * A new `QuerySegments` is the analogous query segment iterator.
  * Once set, `expires` on private cookies is not overwritten. (resolves #1506)
  * `Origin::path()` and `Origin::query()` return `&RawStr`, not `&str`.

Codegen
  * Preserve more spans in `uri!` macro.
  * Preserve spans `FromForm` field types.
  * All dynamic parameters in a query string must typecheck as `FromForm`.
  * `FromFormValue` derive removed; `FromFormField` added.
  * The `form` `FromForm` and `FromFormField` field attribute is now named
    `field`. `#[form(field = ..)]` is now `#[field(name = ..)]`.

Contrib
  * `Json` implements `FromForm`.
  * `MsgPack` implements `FromForm`.
  * The `json!` macro is exported as `rocket_contrib::json::json!`.
  * Added clarifying docs to `StaticFiles`.

Examples
  * `form_validation` and `form_kitchen_sink` removed in favor of `forms`.
  * The `hello_world` example uses unicode in paths.
  * The `json` example only allocates as necessary.

Internal
  * Codegen uses new `exports` module with the following conventions:
    - Locals starts with `__` and are lowercased.
    - Rocket modules start with `_` and are lowercased.
    - `std` types start with `_` and are titlecased.
    - Rocket types are titlecased.
  * A `header` module was added to `http`, contains header types.
  * `SAFETY` is used as doc-string keyword for `unsafe` related comments.
  * The `Uri` parser no longer recognizes Rocket route URIs.
2021-03-04 01:51:21 -08:00
Sergio Benitez c24f15c18f Add regression test for #1503.
Closes #1503.
2021-01-14 15:15:57 -08:00
Sergio Benitez 407e346a6a Clean up 'on_launch_fairing_can_inspect_port' test. 2021-01-13 17:20:44 -08:00
Filip Gospodinov 48fd83a31d Run launch fairings after effective port is known. 2021-01-13 17:20:33 -08:00
Sergio Benitez 28976a5bd3 Preserve 'secret_key' in 'Config' provider data.
Also fixes emission of 'secret_key' warnings when 'secrets' feature is
disabled.

Resolves #1505.
Fixes #1510.
2021-01-13 16:01:39 -08:00