Commit Graph

22 Commits

Author SHA1 Message Date
Sergio Benitez
c2936fcb1e Update 'yansi' to 1.0.0-rc. 2023-07-11 13:18:35 -07:00
Sergio Benitez
d24b5d4d6d Handle more cases in 'AdHoc::normalizer()'.
The compatibility normalizer previously missed or was overly egregious
in several cases. This commit resolves those issue. In particular:

  * Only request URIs that would not match any route are normalized.

  * Synthetic routes are added to the igniting `Rocket` so that requests
    with URIs of the form `/foo` match routes with URIs of the form
    `/foo/<b..>`, as they did prior to the trailing slash overhaul.

Tests are added for all of these cases.
2023-05-04 17:30:37 -07:00
Sergio Benitez
541952bc58 Paint route URI query parts yellow. 2023-05-04 17:30:23 -07:00
Sergio Benitez
56cf905c6e Introduce more flexible mounting.
Prior to this commit, a route with a URI of `/` could not be mounted in
such a way that the resulting effective URI contained a trailing slash.
This commit changes the semantics of mounting so that mounting such a
route to a mount point with a trailing slash yields an effective URI
with a trailing slash. When mounted to points without a trailing slash,
the effective URI does not have a trailing slash.

This commit also introduces the `Route::rebase()` and
`Catcher::rebase()` methods for easier rebasing of existing routes and
catchers.

Finally, this commit improves logging such that mount points of `/`
are underlined in the logs.

Tests and docs were added and modified as necessary.

Resolves #2533.
2023-05-03 20:03:45 -07:00
Sergio Benitez
9b0564ed27 Tidy custom forward status changes, update docs. 2023-04-11 12:55:57 -07:00
Benedikt Weber
055ad107df Allow status customization in 'Forward' outcomes.
Prior to this commit, all forward outcomes resulted in a 404. This
commit changes request and data guards so that they are able to provide
a `Status` on `Forward` outcomes. The router uses this status, if the
final outcome is to forward, to identify the catcher to invoke.

The net effect is that guards can now customize the status code of a
forward and thus the error catcher invoked if the final outcome of a
request is to forward.

Resolves #1560.
2023-04-11 12:47:20 -07:00
Sergio Benitez
b61ac6eb18 Expose 'Route', 'Catcher' collision and matching.
This commit exposes four new methods:

  * `Route::collides_with(&Route)`
  * `Route::matches(&Request)`
  * `Catcher::collides_with(&Catcher)`
  * `Catcher::matches(Status, &Request)`

Each method checks the corresponding condition: whether two routes
collide, whether a route matches a request, whether two catchers
collide, and whether a catcher matches an error arising from a request.

This functionality is used internally by Rocket to make routing
decisions. By exposing these methods, external libraries can use
guaranteed consistent logic to check the same routing conditions.

Resolves #1561.
2023-04-10 22:00:54 -07:00
Sergio Benitez
3a44b1b28e Hide 'RouteUri' fields to ensure URI coherence.
Prior to this commit, several `RouteUri` fields were public, allowing
those values to be changed at will. These changes were at times not
reflected by the rest of the library, meaning that the values in the
route URI structure for a route became incoherent with the reflected
values. This commit makes all fields private, forcing all changes to go
through methods that can ensure coherence. All values remain accessible
via getter methods.
2023-04-10 13:26:54 -07:00
Sergio Benitez
908a918e8b Fuzz to validate routing collision safety.
The fuzzing target introduced in this commit attemps to assert
"collision safety". Formally, this is the property that:

  matches(request, route) := request is matched to route
  collides(route1, route2) := there is a a collision between routes

  forall requests req. !exist routes r1, r2 s.t.
    matches(req, r1) AND matches(req, r2) AND not collides(r1, r2)

Alternatively:

  forall requests req, routes r1, r2.
    matches(req, r1) AND matches(req, r2) => collides(r1, r2)

The target was run for 20 CPU hours without failure.
2023-04-07 20:27:56 -07:00
Sergio Benitez
ac0a77bae2 Allow dynamic parameters to match empty segments.
The net effect of this commit is three-fold:

  * A request to `/` now matches `/<a>`. `/foo/` matches `/<a>/<b>`.
  * A segment matched to a dynamic parameter may be empty.
  * A request to `/foo/` no longer matches `/foo` or `/<a>`. Instead,
    such a request would match `/foo/<a>` or `/foo/`.

The `&str` and `String` parameter guards were updated to reflect this
change: they now error, with a newly introduced error type `Empty` in
the `rocket::error` module, when the parameter is empty. As this was the
only built-in parameter guard that would be effected by this change (all
other guards already required nonempty parameters to succeed), the
majority of applications will see no effect as a result.

For applications wanting the previous functionality, a new
`AdHoc::uri_normalizer()` fairing was introduced.
2023-04-07 20:00:09 -07:00
Sergio Benitez
0a56312607 Implement more conservative URI normalization.
* Trailing slashes are now allowed in all normalized URI paths, except
    for route attribute URIs: `/foo/` is considered normalized.
  * Query parts of URIs may now be empty: `/foo?` and `/foo/?` are now
    considered normalized.
  * The `base` field of `Catcher` is now only accessible via a new
    getter method: `Catcher::base()`.
  * `RawStr::split()` returns a `DoubleEndedIterator`.
  * Introduced a second normalization for `Origin`, "nontrailing", and
    associated methods: `Origin::normalize_nontrailing()`, and
    `Origin::is_normalized_nontrailing()`.
  * Added `Origin::has_trailing_slash()`.
  * The `Segments<Path>` iterator will now return an empty string if
    there is a trailing slash in the referenced path.
  * `Segments::len()` is now `Segments::num()`.
  * Added `RawStr::trim()`.

Resolves #2512.
2023-04-07 19:59:57 -07:00
Sergio Benitez
219a8a5468 Fix a bunch of typos. 2023-03-23 16:27:08 -07:00
Sergio Benitez
0ba5aac53e Update codebase for latest nightly and stable. 2022-02-16 10:08:55 -08:00
Sergio Benitez
a7f6fb2363 Track caller in 'mount' and 'register' calls. 2021-08-19 19:43:34 -07:00
Mikail Bagishov
be933ce398 Apply clippy suggestions. 2021-06-30 14:13:19 -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
0aa9a11ca4 Fix typos throughout codebase. 2021-06-07 19:31:21 -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
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
fe4d0425e6 Remove unnecessary second 'Handler' lifetimes. 2021-04-14 22:17:21 -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