diff --git a/site/guide/01-upgrading-from-0.4.md b/site/guide/01-upgrading-from-0.4.md index 1b362c63..b948b8b7 100644 --- a/site/guide/01-upgrading-from-0.4.md +++ b/site/guide/01-upgrading-from-0.4.md @@ -1,12 +1,12 @@ # Upgrading -Rocket v0.5 bring many new features and improvements over Rocket v0.4. Along -with new features, Rocket v0.5 also includes many changes that improve the -overall usability, stability, and security of the framework and applications -written in it. While the Rust compiler can guide you through many of these -changes, others require special attention. The intent of this guide is to guide -you through these changes and more, migrating your Rocket application to 0.5 and -reaping the benefits of new features and improvements. +Rocket v0.5 bring many new features and improvements over Rocket v0.4. Rocket +v0.5 also includes many changes that improve the overall usability, stability, +and security of the framework and applications written in it. While the Rust +compiler can guide you through many of these changes, others require special +attention. The intent of this guide is to guide you through these changes and +more, migrating your Rocket application to 0.5 and reaping the benefits of new +features and improvements. This guide is _not_ intended to replace, but instead complement, a reading of the [CHANGELOG]. The [CHANGELOG] should be considered required reading for all @@ -14,6 +14,15 @@ developers wishing to migrate their applications to Rocket v0.5. [CHANGELOG]: @github/CHANGELOG.md +! note Don't panic! + + Simply upgrading Rocket's version string to the `0.5` series will result in + _many_ `rustc` compiler errors. But don't let this phase you! The vast + majority of changes are simple renames and `#[async_trait]` attributions which + manifest in a cascading of errors. As such, resolving _one_ top-level issue, + typically requiring minimal, trivial changes, often resolves _many_ errors in + one go. + ## Crate Organization Rocket v0.5 incorporates an improved module structure and crate ecosystem. @@ -55,18 +64,16 @@ to `Cargo.toml`: + rocket_dyn_templates = { version = "0.1.0-rc.1", features = ["tera"] } ``` -! note: `rocket_dyn_templates` _does not_ follow in version lock-step with - the `rocket` crate. +! note: `rocket_dyn_templates` (and co.) _does not_ follow in version lock-step +with the `rocket` crate. This is intentional. The crate depends on many external dependencies which may evolve at a different pace than Rocket itself. Allowing their versions to diverge enables keeping dependencies up-to-date without breaking `rocket` itself. -All features previously present in `rocket_contrib` are available elsewhere. The -[contrib graduation] section of the CHANGELOG contains full details on the -changes. - +All features previously in `rocket_contrib` are available. Consult the [contrib +graduation] section of the CHANGELOG for full details. [`rocket_dyn_templates`]: @api/rocket_dyn_templates [`rocket_sync_db_pools`]: @api/rocket_sync_db_pools @@ -101,7 +108,7 @@ If you prefer to use Rust's stable release channel, you can switch to it using ```sh ## switch globally -rustup default nightly +rustup default stable ## switch locally rustup override set stable @@ -110,9 +117,8 @@ rustup override set stable Using the stable release channel ensures that _no_ breakages will occur when upgrading your Rust compiler or Rocket. That being said, Rocket continues to take advantage of features only present in the nightly channel. As a result, the -development experience will continue to be better on nightly for the forseeable -future. For example, compiler diagnostics on `nightly` are more detailed and -accurate: +development experience will be superior on nightly for the forseeable future. +For example, compiler diagnostics on `nightly` are more detailed and accurate:
Example Diagnostic on Nightly @@ -179,7 +185,7 @@ The new asynchronous core requires an async runtime to run. The new [`launch`] and [`main`] attributes simplify starting a runtime suitable for running Rocket applications. You should use [`launch`] whenever possible. -At the same time, the `rocket::ignite()` function has been renamed to +Additionally, the `rocket::ignite()` function has been renamed to [`rocket::build()`]; calls to the function or method should be replaced accordingly. Together, these two changes result in the following diff to what was previously the `main` function: @@ -204,18 +210,19 @@ Rocket v0.5 takes advantage of the latest developments in async I/O in Rust by migrating to a fully asynchronous core powered by [`tokio`]. Specifically, _every_ request is handled by an asynchronous task which internally calls one or more request handlers. Asynchronous tasks are multiplexed on a [configurable -number of worker threads]. Though there is no limit on the number of tasks that -can run concurrently, at most `worker` tasks can be run in parallel. +number of worker threads]. Though there is no limit to the number of tasks that +can run concurrently, at most `worker` tasks can run in parallel. -The runtime can switch between tasks in a single worker thread _iff_ an `await` -point in reached. In other words, context switching is _cooperative_, _not_ -preemptive. This _iff_ is critical: if an `await` point is _not_ reached, no -task switching can occur. As such, it is important that `await` points occur -periodically in a task so that tasks waiting to be scheduled are not starved. +The runtime can switch between tasks in a single worker thread _iff_ (_if +and only if_) an `await` point in reached. In other words, context +switching is _cooperative_, _not_ preemptive. This _iff_ is critical: if an +`await` point is _not_ reached, no task switching can occur. As such, it is +important that `await` points occur periodically in a task so that tasks waiting +to be scheduled are not starved. -In general, when working with `async` APIs, await points will occur naturally. -However, an application written for synchronous I/O, like all Rocket -applications prior to 0.4, must take great care to convert all synchronous, +In general, when working with `async` APIs, await points occur naturally. +However, an application written for synchronous I/O, including all Rocket +applications prior to v0.5, must take great care to convert all synchronous, blocking I/O, to `async` I/O. This is because, as the name implies, blocking I/O blocks a thread from making progress until the I/O result is available, meaning that no tasks can be scheduled on the waiting thread, wasting valuable resources @@ -234,8 +241,8 @@ Common sources of blocking I/O and their `async` replacements include: Unfortunately, the Rust compiler provides no support for identifying blocking I/O via lints or compile-time checks: it is up to you to scan your application for sources of blocking I/O and replace them with their `async` counterpart. If -no such counterpart exists, you must execute the I/O in its own thread by using -[`rocket::tokio::task::spawn_blocking`]. +no such counterpart exists, you should execute the relevant I/O in its own +thread by using [`rocket::tokio::task::spawn_blocking`]. All of Rocket's I/O APIs have been updated to be `async`-safe. This results in requiring `.await` calls for common APIs like [`NamedFile`]. To @@ -251,6 +258,11 @@ async fn index() -> Option { } ``` +! warning: Non-`async` routes are _also_ executed on the `async` runtime. + + A route that _isn't_ declared as `async` is _still_ executed on the `async` + runtime. As a result, it should not execute blocking I/O. +
See a diff of the changes from v0.4. @@ -343,7 +355,7 @@ of truth for trait and method signatures. ## Configuration -Rocket's configuration system has been entirely revamped for 0.5. The +Rocket's configuration system has been entirely revamped for v0.5. The [configuration](../configuration) section of the guide contains a full walkthrough of the new system while the [general changes] section of the CHANGELOG contains further details on configuration changes. We call out the @@ -366,7 +378,7 @@ detected. The new system deals with "profiles" where there were previously "environments". As opposed to environments, profiles: - * Can be arbitrarily named, and any number can exist. + * Can be arbitrarily named and any number can exist. * Match Rust profiles in naming: `debug` and `release` are the default profiles for the respective Rust compilation profile. * Are programmatically selectable and configurable. @@ -449,7 +461,7 @@ Rocket v0.5 brings several major changes that affect routing: Default route ranking now takes into account partially dynamic paths, increasing the range of default ranks from `[-6, -1]` to `[-12, -1]`. The net effect is that fewer routes collide by default, requiring less manual ranking. For -example, the following two routes collide in 0.4 but not in 0.5: +example, the following two routes collide in v0.4 but not in v0.5: ```rust # use rocket::get; @@ -479,7 +491,7 @@ fn everything() { } For smaller applications, you may find that _all_ manual ranks can be removed. Larger applications may still require ranks to resolve ambiguities. -### Kleen Multi-Segments +### Kleene Multi-Segments The multi-segment route parameter `` now matches _zero or more_ segments, a change from the previous _one_ or more segments. The implication is two-fold: @@ -587,10 +599,12 @@ Rocket v0.5 introduces entirely revamped [forms] with support for: * [Ad-Hoc validation.](../requests#ad-hoc-validation) Additionally, the [`FromForm` derive] has been substantially improved so that -nearly all custom implementations of `FromForm` or (the now defunct) -`FromFormValue` can be derived. Altogether, this means that any external crate -dependency for form handling and most custom `FromForm` or `FromFormValue` -implementations are unnecessary and should be removed. +nearly all custom implementations of `FromForm` or [`FromFormField`], which +replaces `FromFormValue` from v0.4, can be derived. Altogether, this means that +any external crate dependency for form handling and most custom `FromForm` or +`FromFormValue` implementations are unnecessary and should be removed. + +[`FromFormField`]: @api/rocket/form/trait.FromFormField.html ### Multipart @@ -800,7 +814,8 @@ fn stream(n: Option) -> EventStream![] { If you run into any issues upgrading, we encourage you to ask questions via [GitHub discussions] or via chat at [`#rocket:mozilla.org`] on Matrix or the -bridged [`#rocket`] IRC channel at `irc.libera.chat`. +bridged [`#rocket`] IRC channel at `irc.libera.chat`. The [FAQ](../faq/) also +provides answers to commonly asked questions. [GitHub discussions]: https://github.com/SergioBenitez/Rocket/discussions [`#rocket:mozilla.org`]: https://chat.mozilla.org/#/room/#rocket:mozilla.org diff --git a/site/guide/11-conclusion.md b/site/guide/11-conclusion.md index 98567f16..5c057e63 100644 --- a/site/guide/11-conclusion.md +++ b/site/guide/11-conclusion.md @@ -11,7 +11,8 @@ If you find yourself having trouble developing Rocket applications, you can get help via chat at [`#rocket:mozilla.org`] on Matrix or the bridged [`#rocket`] IRC channel on Libera.Chat at `irc.libera.chat`. We recommend joining us on [Matrix via Element]. If you prefer IRC, you can join via the [Kiwi IRC client] -or a client of your own. +or a client of your own. The [FAQ](../faq/) also provides answers to commonly +asked questions. [`#rocket:mozilla.org`]: https://chat.mozilla.org/#/room/#rocket:mozilla.org [`#rocket`]: https://kiwiirc.com/client/irc.libera.chat/#rocket diff --git a/site/guide/12-faq.md b/site/guide/12-faq.md index 989c38b4..24b17e11 100644 --- a/site/guide/12-faq.md +++ b/site/guide/12-faq.md @@ -17,34 +17,35 @@ Is Rocket a monolithic framework like Rails? Or is it more like Flask? Neither! -Rocket's core is small yet complete when it comes to security and correctness. -It mainly consists of: +Rocket's core is small yet complete with respect to security and correctness. It +mainly consists of: * Guard traits like [`FromRequest`] and [`FromData`]. - * Derive macros for all commonly used traits. + * Derive macros for all common traits. * Attribute macros for routing. * Thorough compile and launch-time checking. - * Optional features to enable functionality like TLS, secrets, and so on. * Zero-copy parsers and validators for common formats like multipart and SSE. * Syntax sugar extensions for features like async streams and traits. + * Optional features for functionality like TLS, secrets, and so on. The goal is for functionality like templating, sessions, ORMs, and so on to be -implemented entirely outside of Rocket and yet feel first-class. Indeed, crates -like [`rocket_dyn_templates`] and [`rocket_db_pools`] do just this. +implemented entirely outside of Rocket while maintaining a first-class feel and +experience. Indeed, crates like [`rocket_dyn_templates`] and [`rocket_db_pools`] +do just this. As a result, Rocket is neither "bare-bones" nor is it a kitchen +sink for all possible features. -As a result, Rocket is neither "bare-bones" nor is it a kitchen sink for all -possible features. Unlike other frameworks in the Rust ecosystem, Rocket makes -it its mission to help you avoid security and correctness blunders -out-of-the-box. It does this by including, out-of-the-box: +Unlike other frameworks, Rocket makes it its mission to help you avoid security +and correctness blunders. It does this by including, out-of-the-box: - * A flexible, type-based configuration system. - * Security and privacy headers by default. - * Zero-Copy RFC compliant URI parsers. - * Safe, typed URIs with compile-time checking. - * Thorough compile-time and launch-time checking of routes. - * A complete testing framework with sync and `async` variants. + * A flexible, type-based [configuration](../configuration/) system. + * [Security and privacy headers](@api/rocket/shield/) by default. + * Zero-Copy RFC compliant [URI parsers](@api/rocket/http/uri). + * Safe, [typed URIs](@api/rocket/macro.uri.html) with compile-time checking. + * [Compile-time and launch-time route checking](@api/rocket/attr.route.html). + * A [testing framework](@api/rocket/local) with sync and `async` variants. * Safe, exclusive access to fully decoded HTTP values. - * Mandatory data limits to prevent trivial DoS attacks. + * Mandatory [data limits](@api/rocket/data/struct.Limits.html) to prevent + trivial DoS attacks. Of course, this functionality comes at a compile-time cost (but notably, _not_ at a runtime cost), impacting Rocket's clean build-time. For comparison, here's @@ -104,13 +105,15 @@ Can I use Rocket in production? Should I? It's only v0.x!
We **enthusiastically** recommend using Rocket in production, with the following -caveats: +non-exhaustive list of caveats: 1. Run Rocket behind a reverse proxy like HAProxy or in a production load balancing environment. Rocket (Hyper) doesn't employ any defenses against - DDoS attacks or certain DoS attacks. + DDoS attacks or certain DoS attacks which can be mitigated by an external + service. - 2. Use a TLS termination proxy for zero-downtown certificate rotation. + 2. Use a TLS termination proxy (perhaps from 1.) for zero-downtown certificate + rotation. 3. Properly configure your databases and database pools, especially with respect to the pool size. @@ -157,8 +160,8 @@ So what about benchmarks? Well, benchmarking is _hard_, and besides often being conducted incorrectly, often appear to say more than they do. So, when you see a benchmark for "Hello, world!", you should know that the benchmark's relevance doesn't extend far beyond "Hello, world!" servers and the specific way the -measurement was taken. In other words, they provide only a baseline truth that -is hard to extrapolate to real-world use-cases, _your_ use-case. +measurement was taken. In other words, it provides a baseline truth that is hard +to extrapolate to real-world use-cases, _your_ use-case. Nevertheless, here are some things you can consider as _generally_ true about Rocket applications: @@ -228,7 +231,8 @@ Rocket represents an ecosystem-wide effort to create a web framework that enables writing web applications with unparalleled security, performance, and usability. From design to implementation to documentation, Rocket is carefully crafted to ensure the greatest productivity and reliability with the fewest -surprises. Our goal is to make Rocket the obvious choice across _all_ languages. +surprises. Our goal is to make Rocket a compelling choice across _all_ +languages. Accomplishing this takes time, and our efforts extend to the entire ecosystem. For example, work for Rocket v0.5 included: @@ -314,7 +318,7 @@ For a quick example on how to handle file uploads, see [multipart forms]. File uploads are transmitted by the browser as [multipart] form submissions, which Rocket handles natively as a [`DataField`]. The [`TempFile`] form guard -can accept a `DataField` and stream the data to disk to then be persisted. +can accept a `DataField` and stream the data to disk for persistence.
@@ -339,8 +343,8 @@ converted into useful typed values _before_ being processed. Allowing a Instead, Rocket's handlers work through _guards_, reified as traits, which validate and extract parts of a request as needed. Rocket automatically invokes these guards for you, so custom guards are write-once-use-everywhere. Rocket -won't invoke handlers that depend on guards that fail. This way, handlers only -deal with fully validated, typed, secure values. +won't invoke a handler with failing guards. This way, handlers only deal with +fully validated, typed, secure values. Rocket provides all of the guard implementations you would expect out-of-the-box, and you can implement your own, too. See the following: @@ -375,18 +379,17 @@ reasons. The rest are set by a type's [`Responder`] implementation. **Status** -Rocket automatically sets a Status header for all responses. If the `Responder` -doesn't explicitly set a status, it defaults to `200`. Responders like -`Option`, however, _do_ set the status. See the [`Responder`] docs for -details, and the [`status`] module for details on setting a custom Status or -overriding an existing one. +Rocket automatically sets a `Status` header for all responses. If a `Responder` +doesn't explicitly set a status, it defaults to `200`. Some responders, like +`Option`, do set a status. See [`Responder`] and the [`status`] module for +details on setting a custom `Status` or overriding an existing one. **Content-Type** -Rocket automatically sets a Content-Type header for most types it implements +Rocket automatically sets a `Content-Type` header for types it implements `Responder` for, so in the common case, there's nothing to do. This includes types like `&str`, `&[u8]`, `NamedFile`, and so on. The [`content`] module docs -have details on setting a custom Content-Type or overriding an existing one. +details setting a custom `Content-Type` or overriding an existing one. **Everything Else** @@ -424,9 +427,10 @@ A `HeaderType` won't exist for custom headers, but you can define your own type. As long as it implements `Into
` for Rocket's [`Header`], the type can be used as a field in derived struct. -You can always implement `Responder` directly. Make sure to leverage existing -responders in your implementation. For example, _don't_ serialize JSON manually. -Instead, use the existing [`Json`] responder, like in the example below: +Alternatively, you can always implement `Responder` directly. Make sure to +leverage existing responders in your implementation. For example, _don't_ +serialize JSON manually. Instead, use the existing [`Json`] responder, like in +the example below: ```rust # #[derive(rocket::serde::Serialize)] @@ -554,10 +558,7 @@ How do I make Rocket a _part_ of my application as opposed to the whole thing?
-If you're developing an application where an HTTP server is a _part_ of the -application instead of being the entire thing, use the `#[main]` attribute and -manually call [`launch()`]: - +Use the `#[main]` attribute and manually call [`launch()`]: ```rust,no_run #[rocket::main] @@ -624,23 +625,29 @@ error[E0277]: the trait bound `Foo: Responder<'_, '_>` is not satisfied = note: required by `respond_to` ``` -...then you're almost certainly depending on libraries which depend on different -versions of `rocket`. A common mistake is to depend on a `contrib` library from -git while also depending on a `crates.io` version of Rocket or vice-versa: +...then you're almost certainly depending, perhaps transitively, on _two +different versions_ of a single library. For example, you may be depending on +`rocket` which depends on `time 0.3` while also depending directly on `time +0.2`. Or you may depending on `rocket` from `crates.io` while depending on a +library that depends on `rocket` from `git`. A common instance of this mistake +is to depend on a `contrib` library from git while also depending on a +`crates.io` version of Rocket or vice-versa: ```toml rocket = "0.5.0-rc.1" rocket_db_pools = { git = "https://github.com/SergioBenitez/Rocket.git" } ``` -This is _never_ correct. In Rust, types from two different versions of a library -or from different providers (like `git` vs. `crates.io`) are _always_ considered -distinct, even if they have the same name. Therefore, even if a type implements -a trait from one library, it _does not_ implement the trait from the other -library (since it is considered to be a _different_, _distinct_ library). In -other words, you can _never_ mix two different published versions of Rocket, a -published version and a `git` version, or two instances from different `git` -revisions. +This is _never_ correct. If libraries or applications interact via types from a +common library, those libraries or applications _must_ specify the _same_ +version of that common library. This is because in Rust, types from two +different versions of a library or from different providers (like `git` vs. +`crates.io`) are _always_ considered distinct, even if they have the same name. +Therefore, even if a type implements a trait from one library, it _does not_ +implement the trait from the other library (since it is considered to be a +_different_, _distinct_ library). In other words, you can _never_ mix two +different published versions of Rocket, a published version and a `git` version, +or two instances from different `git` revisions.
diff --git a/site/guide/index.md b/site/guide/index.md index 6f84aec4..baf55910 100644 --- a/site/guide/index.md +++ b/site/guide/index.md @@ -14,6 +14,8 @@ aspect of Rocket. The sections are: - **[Introduction](introduction/):** introduces Rocket and its philosophy. - **[Quickstart](quickstart/):** presents the minimal steps necessary to run your first Rocket application. + - **[Upgrading from v0.4](upgrading-from-0.4/):** a migration guide from v0.4 + to v0.5. - **[Getting Started](getting-started/):** a gentle introduction to getting your first Rocket application running. - **[Overview](overview/):** describes the core concepts of Rocket. @@ -38,7 +40,8 @@ aspect of Rocket. The sections are: The official community support channels are [`#rocket:mozilla.org`] on Matrix and the bridged [`#rocket`] IRC channel on Libera.Chat at `irc.libera.chat`. We recommend joining us on [Matrix via Element]. If you prefer IRC, you can join -via the [Kiwi IRC client] or a client of your own. +via the [Kiwi IRC client] or a client of your own. The [FAQ](../faq/) also +provides answers to commonly asked questions. [`#rocket:mozilla.org`]: https://chat.mozilla.org/#/room/#rocket:mozilla.org [`#rocket`]: https://kiwiirc.com/client/irc.libera.chat/#rocket