Previously, `async_main` would extract a full `Config`. This mean that values
like `address` were read and parsed even when they were unused. Should they
exist and be malformed, a configuration error would needlessly arise.
This commit fixes this by only extract values that are subsequently used.
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.
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.
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.
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.
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.
This commit modifies request routing in a backwards incompatible manner.
The change is summarized as: trailing slashes are now significant and
never transparently disregarded. This has the following implications,
all representing behavior that differs from that before this change:
* Route URIs with trailing slashes (`/foo/`, `/<a>/`) are legal.
* A request `/foo/` is routed to route `/foo/` but not `/foo`.
* Similarly, a request `/bar/` is routed to `/<a>/` but not `/<a>`.
* A request `/bar/foo` is not routed to `/<a>/<b>/<c..>`.
A new `AdHoc::uri_normalizer()` fairing was added that recovers the
previous behavior.
In addition to the above, the `Options::NormalizeDirs` `FileServer`
option is now enabled by default to remain consistent with the above
changes and reduce breaking changes at the `FileServer` level.
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.
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.
* 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.
This commit modifies all of the non-empty responders in the
`response::status` module so that they look like `Status<R>(pub R)`.
Prior to this commit, some responders looked like this, while others
contained an `Option<R>`.
Resolves#2351.
This modifies the 'IoHandler::io()' method so that it takes a
'Pin<Box<Self>>', allowing handlers to move internally and assume that
the data is pinned.
The change is then used in the 'ws' contrib crate to allow 'FnOnce'
handlers instead of 'FnMut'. The net effect is that streams, such as
those crated by 'Stream!', are now allowed to move internally.
Since active I/O streams will be closed by graceful shutdown, an error,
as was previously emitted, was necessarily alarmist. This reduces the
severity of the log message to a warning.
This is a two-prong effort. First, we warn on launch if a known key is
used. Second, we document using invalid keys where possible.
Co-authored-by: Jonas Møller <jonas@moesys.no>
Adds an `ip_header` configuration parameter that allows modifying the
header Rocket attempts to use to retrieve the "real IP" address of the
client via `Request` methods like `client_ip()`. Additionally allows
disabling the use of any such header.
Users experience confusion when the server appears to do "nothing" when
compiled in release mode. In reality, the server has started, but it
offers no indication in that direction via log message. Often users
misconfigure the port or address, but that information isn't displayed.
This commit makes it such that only the final "Rocket has launched!"
log message is displayed, which includes the listening address, port,
and protocol.
Due to tokio-rs/tokio#4780, a panicking top-level future combined with
an uncooperative background task prevents runtime shutdown. To avoid
this in the case of `Rocket::launch()` returning an `Error`, which
panics on drop if it isn't inspected, we return the `Result` to the
caller (i.e., `main`) instead of the `block_on` future. This prevent the
panic from occuring inside of the `block_on` future and so the runtime
terminates even with uncooperative I/O.
Generates a new method on attributed types, `pool()`, which returns an
opaque reference to a type that can be used to get pooled connections.
Also adds a code-generated example to the crate docs which includes
real, proper function signatures and fully checked examples.
Resolves#1884.
Closes#1972.
Remove 'must_use' on the generic 'Rocket<P>', which was overly
conservative. This change, in effect, marks only 'Rocket<Build>'
'must_use', which is a much more precise implementation of the intended
safety guard.
The core improvement is that `Rocket::launch()` now resolves to
`Ok(Rocket<Ignite>)` on nominal shutdown. Furthermore, shutdown never
terminates the running process.
Other changes directly related to shutdown:
* Runtime worker thread names are now irrelevant to graceful shutdown.
* `ErrorKind::Runtime` was removed; `ErrorKind::Shutdown` was added.
* The `force` config value is only read from the default provider.
* If `force`, Rocket's constructed async runtime is terminated.
Other related changes:
* The exported `hyper` module docs properly reflect public re-exports.
The previous implementation allowed a trivial DoS attack in which the
client need simply maintain open connections with incomplete handshakes.
This commit resolves that by allowing a server worker to progress as
soon as a TCP connection has been established. This comes at the expense
of a more complex implementation necessitated by deficiencies in Hyper.
Potentially resolves#2118.
Previously, the heartbeat message, in its raw form, was ":\n\n". This
commit changes the message to be ":\n".
The former message, when parsed as Server-Sent Events, contained an
empty comment (as desired) _and_ a new line (erroneously). The new line
resulted in emitting any event that was presently being emitted, even if
it wasn't complete. That is, emitting an event partly, such as the
event's data but not its name. Removing the extra new line resolves this
issue and ensures that events aren't interrupted by the heartbeat.
Fixes#2152.
Prior to this commit, 'Vec', 'HashMap', and 'BTreeMap' would parse
leniently irrespetive of the requested parsing strategy. This commit
changes their behavior so that the parsing strategy is respected.
Resolves#2131.
In cc98f98, logging was changed to use a new 'write_out!' macro that
internally used 'write!' instead of 'print!' to log. This had an
unfortunate side-effect: 'libtest' via 'cargo test' no longer captures
the log output of tests.
The reason this occurs is due to the way that Cargo, or rather
`libtest`, captures log output: it uses hidden, unstable functions that
replace a special sink that `print!`, and _only_ `print!` writes to.
Using `write!` directly, as the commit does, bypasses this sink, and so
`cargo` never captures the output.
As a compromise, we only use the better implementation when we're not
compiled with `debug_assertions` or running tests, so at least tests run
in debug-mode won't spew output.