-
Notifications
You must be signed in to change notification settings - Fork 59
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
20 changed files
with
544 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 14 additions & 0 deletions
14
doc_examples/guide/request_data/urlencoded/project-extraction.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
```rust title="src/urlencoded/routes.rs" hl_lines="10" | ||
use pavex::http::StatusCode; | ||
use pavex::request::body::UrlEncodedBody; | ||
#[derive(serde::Deserialize)] | ||
pub struct HomeListing { | ||
address: String, | ||
price: u64, | ||
} | ||
pub fn handler(params: &UrlEncodedBody<HomeListing>) -> StatusCode { | ||
// [...] | ||
} | ||
``` |
10 changes: 10 additions & 0 deletions
10
doc_examples/guide/request_data/urlencoded/project-installation.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
```rust title="src/blueprint.rs" hl_lines="6" | ||
use pavex::blueprint::Blueprint; | ||
use pavex::request::body::UrlEncodedBody; | ||
pub fn blueprint() -> Blueprint { | ||
let mut bp = Blueprint::new(); | ||
UrlEncodedBody::register(&mut bp); // (1)! | ||
// [...] | ||
} | ||
``` |
8 changes: 8 additions & 0 deletions
8
doc_examples/guide/request_data/urlencoded/project-struct_with_attr.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
```rust title="src/urlencoded/routes.rs" hl_lines="2" | ||
// [...] | ||
#[derive(serde::Deserialize)] | ||
pub struct HomeListing { | ||
address: String, | ||
price: u64, | ||
} | ||
``` |
2 changes: 2 additions & 0 deletions
2
doc_examples/guide/request_data/urlencoded/project/.gitignore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
/target | ||
Cargo.lock |
13 changes: 13 additions & 0 deletions
13
doc_examples/guide/request_data/urlencoded/project/Cargo.toml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[package] | ||
name = "urlencoded" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
pavex = { path = "../../../../../libs/pavex" } | ||
pavex_cli_client = { path = "../../../../../libs/pavex_cli_client" } | ||
serde = { version = "1", features = ["derive"] } | ||
cargo_px_env = "0.1" | ||
|
||
[workspace] | ||
members = [".", "server_sdk"] |
8 changes: 8 additions & 0 deletions
8
doc_examples/guide/request_data/urlencoded/project/server_sdk/Cargo.toml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
[package] | ||
name = "urlencoded_server_sdk" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[package.metadata.px.generate] | ||
generator_type = "cargo_workspace_binary" | ||
generator_name = "urlencoded" |
1 change: 1 addition & 0 deletions
1
doc_examples/guide/request_data/urlencoded/project/server_sdk/src/lib.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
|
12 changes: 12 additions & 0 deletions
12
doc_examples/guide/request_data/urlencoded/project/src/blueprint.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
use pavex::blueprint::Blueprint; | ||
use pavex::request::body::UrlEncodedBody; | ||
|
||
pub fn blueprint() -> Blueprint { | ||
let mut bp = Blueprint::new(); | ||
UrlEncodedBody::register(&mut bp); // (1)! | ||
pavex::request::body::BufferedBody::register(&mut bp); | ||
pavex::request::body::BodySizeLimit::register(&mut bp); | ||
|
||
bp.nest(crate::urlencoded::blueprint()); | ||
bp | ||
} |
7 changes: 7 additions & 0 deletions
7
doc_examples/guide/request_data/urlencoded/project/src/lib.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#![allow(dead_code)] | ||
#![allow(unused_variables)] | ||
|
||
pub use blueprint::blueprint; | ||
|
||
mod blueprint; | ||
pub mod urlencoded; |
13 changes: 13 additions & 0 deletions
13
doc_examples/guide/request_data/urlencoded/project/src/main.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
use std::error::Error; | ||
|
||
use cargo_px_env::generated_pkg_manifest_path; | ||
use urlencoded::blueprint; | ||
use pavex_cli_client::Client; | ||
|
||
fn main() -> Result<(), Box<dyn Error>> { | ||
let generated_dir = generated_pkg_manifest_path()?.parent().unwrap().into(); | ||
Client::new() | ||
.generate(blueprint(), generated_dir) | ||
.execute()?; | ||
Ok(()) | ||
} |
9 changes: 9 additions & 0 deletions
9
doc_examples/guide/request_data/urlencoded/project/src/urlencoded/blueprint.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
use pavex::blueprint::router::GET; | ||
use pavex::blueprint::Blueprint; | ||
use pavex::f; | ||
|
||
pub fn blueprint() -> Blueprint { | ||
let mut bp = Blueprint::new(); | ||
bp.route(GET, "/search", f!(super::handler)); | ||
bp | ||
} |
5 changes: 5 additions & 0 deletions
5
doc_examples/guide/request_data/urlencoded/project/src/urlencoded/mod.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
pub use blueprint::blueprint; | ||
pub use routes::handler; | ||
|
||
mod blueprint; | ||
mod routes; |
12 changes: 12 additions & 0 deletions
12
doc_examples/guide/request_data/urlencoded/project/src/urlencoded/routes.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
use pavex::http::StatusCode; | ||
use pavex::request::body::UrlEncodedBody; | ||
|
||
#[derive(serde::Deserialize)] | ||
pub struct HomeListing { | ||
address: String, | ||
price: u64, | ||
} | ||
|
||
pub fn handler(params: &UrlEncodedBody<HomeListing>) -> StatusCode { | ||
StatusCode::OK | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
starter_project_folder: "project" | ||
commands: | ||
- command: "cargo px c" | ||
expected_outcome: "success" | ||
snippets: | ||
- name: "installation" | ||
source_path: "src/blueprint.rs" | ||
ranges: [ "0..6", "11..12" ] | ||
hl_lines: [ 6 ] | ||
- name: "extraction" | ||
source_path: "src/urlencoded/routes.rs" | ||
ranges: [ "0..10", "11..12" ] | ||
hl_lines: [ 10 ] | ||
- name: "struct_with_attr" | ||
source_path: "src/urlencoded/routes.rs" | ||
ranges: [ "3..8" ] | ||
hl_lines: [ 2 ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
# UrlEncoded | ||
|
||
[`UrlEncodedBody<T>`][UrlEncodedBody] buffers the body in memory and deserializes it as URL-encoded, | ||
according to the type `T` you specify. | ||
|
||
## Registration | ||
|
||
To use [`UrlEncodedBody<T>`][UrlEncodedBody] in your application you need to register a constructor for it. | ||
You can use [`UrlEncodedBody::register`][UrlEncodedBody::register] to register the default constructor | ||
and error handler: | ||
|
||
--8<-- "doc_examples/guide/request_data/urlencoded/project-installation.snap" | ||
|
||
1. You also need to register a constructor for [`BufferedBody`][BufferedBody]! | ||
Check out the [BufferedBody guide](../byte_wrappers.md) for more details. | ||
|
||
If you're using the default [`ApiKit`](../../../dependency_injection/core_concepts/kits.md), | ||
you don't need to register a constructor for [`BufferedBody`][BufferedBody] manually: | ||
it's already included in the kit. | ||
|
||
## Extraction | ||
|
||
Inject [`UrlEncodedBody<T>`][UrlEncodedBody] as an input in your components to access the parsed body: | ||
|
||
--8<-- "doc_examples/guide/request_data/urlencoded/project-extraction.snap" | ||
|
||
## Deserialization | ||
|
||
The newly defined struct must be **deserializable**—i.e. it must implement | ||
the [`serde::Deserialize`][serde::Deserialize] trait. | ||
You can derive [`serde::Deserialize`][serde::Deserialize] in most cases. | ||
|
||
--8<-- "doc_examples/guide/request_data/urlencoded/project-struct_with_attr.snap" | ||
|
||
## Unsupported field types | ||
|
||
[`UrlEncodedBody<T>`][UrlEncodedBody] doesn't support deserializing nested structures. | ||
For example, the following can't be deserialized from the wire using [`UrlEncodedBody<T>`][UrlEncodedBody]: | ||
|
||
```rust | ||
#[derive(serde::Deserialize)] | ||
pub struct UpdateUserBody { | ||
address: Address | ||
} | ||
|
||
#[derive(serde::Deserialize)] | ||
pub struct Address { | ||
street: String, | ||
city: String, | ||
} | ||
``` | ||
|
||
If you need to deserialize nested structures from an urlencoded body, | ||
you might want to look into writing your own extractor on top of [`serde_qs`](https://crates.io/crates/serde_qs). | ||
|
||
## Avoiding allocations | ||
|
||
If you want to minimize memory usage, you can try to avoid unnecessary heap memory allocations when deserializing | ||
string-like fields from the body of the incoming request. | ||
Pavex supports this use case—**you can borrow from the request body**. | ||
|
||
### Percent-encoding | ||
|
||
It is not always possible to avoid allocations when handling an urlencoded body. | ||
A urlencoded body must comply with the restriction of the URI specification: | ||
you can only use [a limited set of characters](https://datatracker.ietf.org/doc/html/rfc3986#section-2). | ||
If you want to use a character not allowed in a URI, you | ||
must [percent-encode it](https://developer.mozilla.org/en-US/docs/Glossary/Percent-encoding). | ||
For example, if you want to use a space in a field name or a field value, you must encode it as `%20`. | ||
A string like `John Doe` becomes `John%20Doe` when percent-encoded. | ||
|
||
[`UrlEncodedBody<T>`][UrlEncodedBody] automatically decodes percent-encoded strings for you. But that comes at a cost: | ||
Pavex _must_ allocate a new `String` if the route parameter is percent-encoded. | ||
|
||
### Cow | ||
|
||
We recommend using [`Cow<'_, str>`][Cow] as your field type for string-like parameters. | ||
It borrows from the request's path if possible, it allocates a new `String` if it can't be avoided. | ||
|
||
[`Cow<'_, str>`][Cow] strikes a balance between performance and robustness: you don't have to worry about a runtime | ||
error if the route parameter | ||
is percent-encoded, but you tried to use `&str` as its field type. | ||
|
||
[BufferedBody]: ../../../../api_reference/pavex/request/body/struct.BufferedBody.html | ||
|
||
[UrlEncodedBody]: ../../../../api_reference/pavex/request/body/struct.UrlEncodedBody.html | ||
|
||
[UrlEncodedBody::register]: ../../../../api_reference/pavex/request/body/struct.UrlEncodedBody.html#method.register | ||
|
||
[serde::Deserialize]: https://docs.rs/serde/latest/serde/trait.Deserialize.html | ||
|
||
[Cow]: https://doc.rust-lang.org/std/borrow/enum.Cow.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.