mirror of https://github.com/rwf2/Rocket.git
Graduate contrib 'uuid' into core.
This has the following nice benefits: * The 'Uuid' wrapper type is gone. * 'Uuid' implements 'UriDisplay', 'FromUriParam'. * The 'serialization' example merges in 'uuid'. Resolves #1299.
This commit is contained in:
parent
f6a7087c84
commit
a78814f1c5
|
@ -27,7 +27,6 @@ serve = []
|
|||
compression = ["brotli_compression", "gzip_compression"]
|
||||
brotli_compression = ["brotli"]
|
||||
gzip_compression = ["flate2"]
|
||||
uuid = ["serde", "_uuid"]
|
||||
|
||||
# The barage of user-facing database features.
|
||||
diesel_sqlite_pool = ["databases", "diesel/sqlite", "diesel/r2d2"]
|
||||
|
@ -69,12 +68,6 @@ r2d2-memcache = { version = "0.6", optional = true }
|
|||
brotli = { version = "3.3", optional = true }
|
||||
flate2 = { version = "1.0", optional = true }
|
||||
|
||||
[dependencies._uuid]
|
||||
package = "uuid"
|
||||
version = ">=0.7.0, <0.9.0"
|
||||
optional = true
|
||||
features = ["serde"]
|
||||
|
||||
[dev-dependencies]
|
||||
serde_test = "1.0.114"
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
//! * [serve*](serve) - Static File Serving
|
||||
//! * [handlebars_templates](templates) - Handlebars Templating
|
||||
//! * [tera_templates](templates) - Tera Templating
|
||||
//! * [uuid](uuid) - UUID (de)serialization
|
||||
//! * [${database}_pool](databases) - Database Configuration and Pooling
|
||||
//!
|
||||
//! The recommend way to include features from this crate via Rocket in your
|
||||
|
@ -42,7 +41,6 @@
|
|||
|
||||
#[cfg(feature="serve")] pub mod serve;
|
||||
#[cfg(feature="templates")] pub mod templates;
|
||||
#[cfg(feature="uuid")] pub mod uuid;
|
||||
#[cfg(feature="databases")] pub mod databases;
|
||||
// TODO.async: Migrate compression, reenable this, tests, and add to docs.
|
||||
//#[cfg(any(feature="brotli_compression", feature="gzip_compression"))] pub mod compression;
|
||||
|
|
|
@ -1,203 +0,0 @@
|
|||
//! UUID parameter and form value parsing support.
|
||||
//!
|
||||
//! See the [`Uuid`] type for further details.
|
||||
//!
|
||||
//! # Enabling
|
||||
//!
|
||||
//! This module is only available when the `uuid` feature is enabled. Enable it
|
||||
//! in `Cargo.toml` as follows:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies.rocket_contrib]
|
||||
//! version = "0.5.0-dev"
|
||||
//! default-features = false
|
||||
//! features = ["uuid"]
|
||||
//! ```
|
||||
|
||||
pub extern crate _uuid as extern_uuid;
|
||||
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
use std::ops::Deref;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use rocket::request::FromParam;
|
||||
use rocket::form::{self, FromFormField, ValueField};
|
||||
|
||||
/// UUID data and form guard: consume UUID values.
|
||||
///
|
||||
/// `Uuid` implements [`FromParam`] and [`FromFormField`], allowing UUID values
|
||||
/// to be accepted directly in paths, queries, and forms.
|
||||
///
|
||||
/// # Usage
|
||||
///
|
||||
/// To use, add the `uuid` feature to the `rocket_contrib` dependencies section
|
||||
/// of your `Cargo.toml`:
|
||||
///
|
||||
/// ```toml
|
||||
/// [dependencies.rocket_contrib]
|
||||
/// version = "0.5.0-dev"
|
||||
/// default-features = false
|
||||
/// features = ["uuid"]
|
||||
/// ```
|
||||
///
|
||||
/// You can use the `Uuid` type directly as a target of a dynamic parameter:
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate rocket;
|
||||
/// # #[macro_use] extern crate rocket_contrib;
|
||||
/// use rocket_contrib::uuid::Uuid;
|
||||
///
|
||||
/// #[get("/users/<id>")]
|
||||
/// fn user(id: Uuid) -> String {
|
||||
/// format!("We found: {}", id)
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// You can also use the `Uuid` as a form value, including in query strings:
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use] extern crate rocket;
|
||||
/// # #[macro_use] extern crate rocket_contrib;
|
||||
/// use rocket_contrib::uuid::Uuid;
|
||||
///
|
||||
/// #[get("/user?<id>")]
|
||||
/// fn user(id: Uuid) -> String {
|
||||
/// format!("User ID: {}", id)
|
||||
/// }
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Serialize, Deserialize)]
|
||||
#[serde(transparent)]
|
||||
pub struct Uuid(_uuid::Uuid);
|
||||
|
||||
pub type Error = <_uuid::Uuid as std::str::FromStr>::Err;
|
||||
|
||||
impl Uuid {
|
||||
/// Consumes the Uuid wrapper, returning the underlying `Uuid` type.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # extern crate rocket_contrib;
|
||||
/// # use std::str::FromStr;
|
||||
/// # fn main() {
|
||||
/// use rocket_contrib::uuid::{extern_uuid, Uuid};
|
||||
///
|
||||
/// let uuid_str = "c1aa1e3b-9614-4895-9ebd-705255fa5bc2";
|
||||
/// let real_uuid = extern_uuid::Uuid::from_str(uuid_str).unwrap();
|
||||
/// let my_inner_uuid = Uuid::from_str(uuid_str)
|
||||
/// .expect("valid UUID string")
|
||||
/// .into_inner();
|
||||
///
|
||||
/// assert_eq!(real_uuid, my_inner_uuid);
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
pub fn into_inner(self) -> _uuid::Uuid {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Uuid {
|
||||
#[inline(always)]
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromParam<'a> for Uuid {
|
||||
type Error = Error;
|
||||
|
||||
/// A value is successfully parsed if `param` is a properly formatted Uuid.
|
||||
/// Otherwise, an error is returned.
|
||||
#[inline(always)]
|
||||
fn from_param(param: &'a str) -> Result<Uuid, Self::Error> {
|
||||
param.parse()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'v> FromFormField<'v> for Uuid {
|
||||
fn from_value(field: ValueField<'v>) -> form::Result<'v, Self> {
|
||||
Ok(field.value.parse().map_err(form::error::Error::custom)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Uuid {
|
||||
type Err = Error;
|
||||
|
||||
#[inline]
|
||||
fn from_str(s: &str) -> Result<Uuid, Self::Err> {
|
||||
s.parse().map(Uuid)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Uuid {
|
||||
type Target = _uuid::Uuid;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<_uuid::Uuid> for Uuid {
|
||||
#[inline(always)]
|
||||
fn eq(&self, other: &_uuid::Uuid) -> bool {
|
||||
self.0.eq(other)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::Uuid;
|
||||
use super::FromParam;
|
||||
use super::FromStr;
|
||||
|
||||
#[test]
|
||||
fn test_from_str() {
|
||||
let uuid_str = "c1aa1e3b-9614-4895-9ebd-705255fa5bc2";
|
||||
let uuid_wrapper = Uuid::from_str(uuid_str).unwrap();
|
||||
assert_eq!(uuid_str, uuid_wrapper.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_param() {
|
||||
let uuid_str = "c1aa1e3b-9614-4895-9ebd-705255fa5bc2";
|
||||
let uuid_wrapper = Uuid::from_param(uuid_str.into()).unwrap();
|
||||
assert_eq!(uuid_str, uuid_wrapper.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_into_inner() {
|
||||
let uuid_str = "c1aa1e3b-9614-4895-9ebd-705255fa5bc2";
|
||||
let uuid_wrapper = Uuid::from_param(uuid_str.into()).unwrap();
|
||||
let real_uuid: _uuid::Uuid = uuid_str.parse().unwrap();
|
||||
let inner_uuid: _uuid::Uuid = uuid_wrapper.into_inner();
|
||||
assert_eq!(real_uuid, inner_uuid)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_partial_eq() {
|
||||
let uuid_str = "c1aa1e3b-9614-4895-9ebd-705255fa5bc2";
|
||||
let uuid_wrapper = Uuid::from_param(uuid_str.into()).unwrap();
|
||||
let real_uuid: _uuid::Uuid = uuid_str.parse().unwrap();
|
||||
assert_eq!(uuid_wrapper, real_uuid)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "InvalidLength")]
|
||||
fn test_from_param_invalid() {
|
||||
let uuid_str = "c1aa1e3b-9614-4895-9ebd-705255fa5bc2p";
|
||||
Uuid::from_param(uuid_str.into()).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ser_de() {
|
||||
// The main reason for this test is to test that UUID only serializes as
|
||||
// a string token, not anything else. Like a Struct with a named field...
|
||||
use serde_test::{Token, assert_tokens, Configure};
|
||||
let uuid: Uuid = "c1aa1e3b-9614-4895-9ebd-705255fa5bc2".parse().unwrap();
|
||||
|
||||
assert_tokens(&uuid.readable(), &[
|
||||
Token::Str("c1aa1e3b-9614-4895-9ebd-705255fa5bc2"),
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ default = []
|
|||
tls = ["tokio-rustls"]
|
||||
private-cookies = ["cookie/private", "cookie/key-expansion"]
|
||||
serde = ["uncased/with-serde-alloc", "_serde"]
|
||||
uuid = ["_uuid"]
|
||||
|
||||
[dependencies]
|
||||
smallvec = "1.0"
|
||||
|
@ -56,5 +57,11 @@ optional = true
|
|||
default-features = false
|
||||
features = ["std"]
|
||||
|
||||
[dependencies._uuid]
|
||||
package = "uuid"
|
||||
version = "0.8"
|
||||
optional = true
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { version = "0.5.0-dev", path = "../lib" }
|
||||
|
|
|
@ -259,12 +259,13 @@ use crate::uri::fmt::{Part, Path, Query, Formatter};
|
|||
/// use rocket::response::Redirect;
|
||||
///
|
||||
/// impl UriDisplay<Path> for Name<'_> {
|
||||
/// // Delegates to the `UriDisplay` implementation for `str` via the call
|
||||
/// // to `write_value` to ensure that the written string is URI-safe. In
|
||||
/// // this case, the string will be percent encoded. Prefixes the inner
|
||||
/// // name with `name:`.
|
||||
/// // Writes the raw string `name:`, which is URI-safe, and then delegates
|
||||
/// // to the `UriDisplay` implementation for `str` which ensures that
|
||||
/// // string is written in a URI-safe manner. In this case, the string will
|
||||
/// // be percent encoded.
|
||||
/// fn fmt(&self, f: &mut Formatter<Path>) -> fmt::Result {
|
||||
/// f.write_value(&format!("name:{}", self.0))
|
||||
/// f.write_raw("name:")?;
|
||||
/// UriDisplay::fmt(&self.0, f)
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
|
@ -408,6 +409,9 @@ impl<T: UriDisplay<Query>, E> UriDisplay<Query> for Result<T, E> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "uuid")] impl_with_display!(_uuid::Uuid);
|
||||
#[cfg(feature = "uuid")] crate::impl_from_uri_param_identity!(_uuid::Uuid);
|
||||
|
||||
// And finally, the `Ignorable` trait, which has sugar of `_` in the `uri!`
|
||||
// macro, which expands to a typecheck.
|
||||
|
||||
|
|
|
@ -24,11 +24,13 @@ tls = ["rocket_http/tls"]
|
|||
secrets = ["rocket_http/private-cookies"]
|
||||
json = ["serde_json", "tokio/io-util"]
|
||||
msgpack = ["rmp-serde", "tokio/io-util"]
|
||||
uuid = ["_uuid", "rocket_http/uuid"]
|
||||
|
||||
[dependencies]
|
||||
# Serialization dependencies.
|
||||
serde_json = { version = "1.0.26", optional = true }
|
||||
rmp-serde = { version = "0.15.0", optional = true }
|
||||
_uuid = { package = "uuid", version = "0.8", optional = true, features = ["serde"] }
|
||||
|
||||
# Non-optional, core dependencies from here on out.
|
||||
futures = "0.3.0"
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
//! | `tls` | Support for [TLS] encrypted connections. |
|
||||
//! | `json` | Support for [JSON (de)serialization]. |
|
||||
//! | `msgpack` | Support for [MessagePack (de)serialization]. |
|
||||
//! | `uuid` | Support for [UUID value parsing and (de)serialization]. |
|
||||
//!
|
||||
//! Features can be selectively enabled in `Cargo.toml`:
|
||||
//!
|
||||
|
@ -74,6 +75,7 @@
|
|||
//!
|
||||
//! [JSON (de)serialization]: crate::serde::json
|
||||
//! [MessagePack (de)serialization]: crate::serde::msgpack
|
||||
//! [UUID value parsing and (de)serialization]: crate::serde::uuid
|
||||
//! [private cookies]: https://rocket.rs/master/guide/requests/#private-cookies
|
||||
//! [TLS]: https://rocket.rs/master/guide/configuration/#tls
|
||||
//!
|
||||
|
|
|
@ -16,3 +16,7 @@ pub mod json;
|
|||
#[cfg(feature = "msgpack")]
|
||||
#[cfg_attr(nightly, doc(cfg(feature = "msgpack")))]
|
||||
pub mod msgpack;
|
||||
|
||||
#[cfg(feature = "uuid")]
|
||||
#[cfg_attr(nightly, doc(cfg(feature = "uuid")))]
|
||||
pub mod uuid;
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
//! UUID path/query parameter and form value parsing support.
|
||||
//!
|
||||
//! # Enabling
|
||||
//!
|
||||
//! This module is only available when the `uuid` feature is enabled. Enable it
|
||||
//! in `Cargo.toml` as follows:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies.rocket]
|
||||
//! version = "0.5.0-dev"
|
||||
//! features = ["uuid"]
|
||||
//! ```
|
||||
//!
|
||||
//! # Usage
|
||||
//!
|
||||
//! `Uuid` implements [`FromParam`] and [`FromFormField`] (i.e,
|
||||
//! [`FromForm`](crate::form::FromForm)), allowing UUID values to be accepted
|
||||
//! directly in paths, queries, and forms. You can use the `Uuid` type directly
|
||||
//! as a target of a dynamic parameter:
|
||||
//!
|
||||
//! ```rust
|
||||
//! # #[macro_use] extern crate rocket;
|
||||
//! use rocket::serde::uuid::Uuid;
|
||||
//!
|
||||
//! #[get("/users/<id>")]
|
||||
//! fn user(id: Uuid) -> String {
|
||||
//! format!("We found: {}", id)
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! You can also use the `Uuid` as a form value, including in query strings:
|
||||
//!
|
||||
//! ```rust
|
||||
//! # #[macro_use] extern crate rocket;
|
||||
//! use rocket::serde::uuid::Uuid;
|
||||
//!
|
||||
//! #[get("/user?<id>")]
|
||||
//! fn user(id: Uuid) -> String {
|
||||
//! format!("User ID: {}", id)
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! Additionally, `Uuid` implements `UriDisplay<P>` for all `P`. As such, route
|
||||
//! URIs including `Uuid`s can be generated in a type-safe manner:
|
||||
//!
|
||||
//! ```rust
|
||||
//! # #[macro_use] extern crate rocket;
|
||||
//! use rocket::serde::uuid::Uuid;
|
||||
//! use rocket::response::Redirect;
|
||||
//!
|
||||
//! #[get("/user/<id>")]
|
||||
//! fn user(id: Uuid) -> String {
|
||||
//! format!("User ID: {}", id)
|
||||
//! }
|
||||
//!
|
||||
//! #[get("/user?<id>")]
|
||||
//! fn old_user_path(id: Uuid) -> Redirect {
|
||||
//! # let _ = Redirect::to(uri!(user(&id)));
|
||||
//! # let _ = Redirect::to(uri!(old_user_path(id)));
|
||||
//! # let _ = Redirect::to(uri!(old_user_path(&id)));
|
||||
//! Redirect::to(uri!(user(id)))
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! # Extra Features
|
||||
//!
|
||||
//! The [`uuid`](https://docs.rs/uuid/0.8) crate exposes extra `v{n}` features
|
||||
//! for generating UUIDs which are not enabled by Rocket. To enable these
|
||||
//! features, depend on `uuid` directly. The extra functionality can be accessed
|
||||
//! via both `rocket::serde::uuid::Uuid` or the direct `uuid::Uuid`; the types
|
||||
//! are one and the same.
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies.uuid]
|
||||
//! version = "0.8"
|
||||
//! features = ["v1", "v4"]
|
||||
//! ```
|
||||
|
||||
use crate::request::FromParam;
|
||||
use crate::form::{self, FromFormField, ValueField};
|
||||
|
||||
/// A Universally Unique Identifier (UUID).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// To parse a UUID and print it as a urn:
|
||||
///
|
||||
/// ```rust
|
||||
/// use rocket::serde::uuid::{Uuid, Error};
|
||||
///
|
||||
/// # fn f() -> Result<(), Error> {
|
||||
/// let uuid = Uuid::parse_str("936DA01F9ABD4d9d80C702AF85C822A8")?;
|
||||
/// println!("{}", uuid.to_urn());
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
pub use _uuid::Uuid;
|
||||
|
||||
pub use _uuid::{Builder, Variant, Version};
|
||||
|
||||
/// Type alias for the error returned on [`FromParam`] or [`FromFormField`]
|
||||
/// failure.
|
||||
pub type Error = <_uuid::Uuid as std::str::FromStr>::Err;
|
||||
|
||||
impl<'a> FromParam<'a> for Uuid {
|
||||
type Error = Error;
|
||||
|
||||
/// A value is successfully parsed if `param` is a properly formatted Uuid.
|
||||
/// Otherwise, an error is returned.
|
||||
#[inline(always)]
|
||||
fn from_param(param: &'a str) -> Result<Uuid, Self::Error> {
|
||||
param.parse()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'v> FromFormField<'v> for Uuid {
|
||||
#[inline]
|
||||
fn from_value(field: ValueField<'v>) -> form::Result<'v, Self> {
|
||||
Ok(field.value.parse().map_err(form::error::Error::custom)?)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::{Uuid, FromParam};
|
||||
|
||||
#[test]
|
||||
fn test_from_param() {
|
||||
let uuid_str = "c1aa1e3b-9614-4895-9ebd-705255fa5bc2";
|
||||
let uuid_wrapper = Uuid::from_param(uuid_str.into()).unwrap();
|
||||
assert_eq!(uuid_str, uuid_wrapper.to_string())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "InvalidLength")]
|
||||
fn test_from_param_invalid() {
|
||||
let uuid_str = "c1aa1e3b-9614-4895-9ebd-705255fa5bc2p";
|
||||
Uuid::from_param(uuid_str.into()).unwrap();
|
||||
}
|
||||
}
|
|
@ -15,7 +15,6 @@ members = [
|
|||
"templating",
|
||||
"testing",
|
||||
"tls",
|
||||
"uuid",
|
||||
|
||||
"pastebin",
|
||||
"todo",
|
||||
|
|
|
@ -60,7 +60,7 @@ This directory contains projects showcasing Rocket's features.
|
|||
|
||||
* **[`serialization`](./serialization)** - Showcases JSON and MessagePack
|
||||
(de)serialization support by implementing a CRUD-like message API in JSON
|
||||
and a simply read/echo API in MessagePack.
|
||||
and a simply read/echo API in MessagePack. Showcases UUID parsing support.
|
||||
|
||||
* **[`state`](./state)** - Illustrates the use of request-local state and
|
||||
managed state. Uses request-local state to cache "expensive" per-request
|
||||
|
@ -80,6 +80,3 @@ This directory contains projects showcasing Rocket's features.
|
|||
|
||||
* **[`tls`](./tls)** - Illustrates configuring TLS with a variety of key pair
|
||||
kinds.
|
||||
|
||||
* **[`uuid`](./uuid)** - Uses UUID support in `contrib`, converting between
|
||||
`contrib::Uuid` type and the `uuid` crate `Uuid`.
|
||||
|
|
|
@ -7,4 +7,4 @@ publish = false
|
|||
|
||||
[dependencies.rocket]
|
||||
path = "../../core/lib"
|
||||
features = ["json", "msgpack"]
|
||||
features = ["json", "msgpack", "uuid"]
|
||||
|
|
|
@ -4,10 +4,12 @@
|
|||
|
||||
mod json;
|
||||
mod msgpack;
|
||||
mod uuid;
|
||||
|
||||
#[launch]
|
||||
fn rocket() -> _ {
|
||||
rocket::build()
|
||||
.attach(json::stage())
|
||||
.attach(msgpack::stage())
|
||||
.attach(uuid::stage())
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use rocket::local::blocking::Client;
|
||||
use rocket::http::{Status, ContentType, Accept};
|
||||
use rocket::serde::{Serialize, Deserialize};
|
||||
use rocket::serde::{Serialize, Deserialize, uuid::Uuid};
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
|
@ -114,3 +114,25 @@ fn msgpack_post() {
|
|||
assert_eq!(res.status(), Status::Ok);
|
||||
assert_eq!(res.into_string().unwrap(), "Goodbye, world!");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn uuid() {
|
||||
let client = Client::tracked(super::rocket()).unwrap();
|
||||
|
||||
let pairs = &[
|
||||
("7f205202-7ba1-4c39-b2fc-3e630722bf9f", "We found: Lacy"),
|
||||
("4da34121-bc7d-4fc1-aee6-bf8de0795333", "We found: Bob"),
|
||||
("ad962969-4e3d-4de7-ac4a-2d86d6d10839", "We found: George"),
|
||||
("e18b3a5c-488f-4159-a240-2101e0da19fd",
|
||||
"Missing person for UUID: e18b3a5c-488f-4159-a240-2101e0da19fd"),
|
||||
];
|
||||
|
||||
for (uuid, response) in pairs {
|
||||
let uuid = Uuid::parse_str(uuid).unwrap();
|
||||
let res = client.get(uri!(super::uuid::people(uuid))).dispatch();
|
||||
assert_eq!(res.into_string().unwrap(), *response);
|
||||
}
|
||||
|
||||
let res = client.get("/people/not-a-uuid").dispatch();
|
||||
assert_eq!(res.status(), Status::NotFound);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use rocket::State;
|
||||
use rocket::serde::uuid::Uuid;
|
||||
|
||||
// A small people mapping in managed state for the sake of this example. In a
|
||||
// real application this would be a database.
|
||||
struct People(HashMap<Uuid, &'static str>);
|
||||
|
||||
#[get("/people/<id>")]
|
||||
fn people(id: Uuid, people: &State<People>) -> Result<String, String> {
|
||||
Ok(people.0.get(&id)
|
||||
.map(|person| format!("We found: {}", person))
|
||||
.ok_or_else(|| format!("Missing person for UUID: {}", id))?)
|
||||
}
|
||||
|
||||
pub fn stage() -> rocket::fairing::AdHoc {
|
||||
// Seed the "database".
|
||||
let mut map = HashMap::new();
|
||||
map.insert("7f205202-7ba1-4c39-b2fc-3e630722bf9f".parse().unwrap(), "Lacy");
|
||||
map.insert("4da34121-bc7d-4fc1-aee6-bf8de0795333".parse().unwrap(), "Bob");
|
||||
map.insert("ad962969-4e3d-4de7-ac4a-2d86d6d10839".parse().unwrap(), "George");
|
||||
|
||||
rocket::fairing::AdHoc::on_ignite("UUID", |rocket| async {
|
||||
rocket
|
||||
.manage(People(map))
|
||||
.mount("/", routes![people])
|
||||
})
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
[package]
|
||||
name = "uuid"
|
||||
version = "0.1.0"
|
||||
workspace = "../"
|
||||
edition = "2018"
|
||||
publish = false
|
||||
|
||||
[dependencies]
|
||||
rocket = { path = "../../core/lib" }
|
||||
|
||||
[dependencies.rocket_contrib]
|
||||
default-features = false
|
||||
path = "../../contrib/lib"
|
||||
features = ["uuid"]
|
|
@ -1,36 +0,0 @@
|
|||
#[macro_use] extern crate rocket;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use rocket::State;
|
||||
use rocket_contrib::uuid::Uuid;
|
||||
use rocket_contrib::uuid::extern_uuid;
|
||||
|
||||
#[cfg(test)] mod tests;
|
||||
|
||||
// A small people mapping in managed state for the sake of this example. In a
|
||||
// real application this would be a database. Notice that we use the external
|
||||
// Uuid type here and not the rocket_contrib::uuid::Uuid type. We do this purely
|
||||
// for demonstrative purposes; in practice, we could use the contrib `Uuid`.
|
||||
struct People(HashMap<extern_uuid::Uuid, &'static str>);
|
||||
|
||||
#[get("/people/<id>")]
|
||||
fn people(id: Uuid, people: &State<People>) -> Result<String, String> {
|
||||
// Because Uuid implements the Deref trait, we use Deref coercion to convert
|
||||
// rocket_contrib::uuid::Uuid to uuid::Uuid.
|
||||
Ok(people.0.get(&id)
|
||||
.map(|person| format!("We found: {}", person))
|
||||
.ok_or_else(|| format!("Person not found for UUID: {}", id))?)
|
||||
}
|
||||
|
||||
#[launch]
|
||||
fn rocket() -> _ {
|
||||
let mut map = HashMap::new();
|
||||
map.insert("7f205202-7ba1-4c39-b2fc-3e630722bf9f".parse().unwrap(), "Lacy");
|
||||
map.insert("4da34121-bc7d-4fc1-aee6-bf8de0795333".parse().unwrap(), "Bob");
|
||||
map.insert("ad962969-4e3d-4de7-ac4a-2d86d6d10839".parse().unwrap(), "George");
|
||||
|
||||
rocket::build()
|
||||
.manage(People(map))
|
||||
.mount("/", routes![people])
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
use super::rocket;
|
||||
use rocket::local::blocking::Client;
|
||||
use rocket::http::Status;
|
||||
|
||||
fn test(uri: &str, expected: &str) {
|
||||
let client = Client::tracked(rocket()).unwrap();
|
||||
let res = client.get(uri).dispatch();
|
||||
assert_eq!(res.into_string(), Some(expected.into()));
|
||||
}
|
||||
|
||||
fn test_404(uri: &str) {
|
||||
let client = Client::tracked(rocket()).unwrap();
|
||||
let res = client.get(uri).dispatch();
|
||||
assert_eq!(res.status(), Status::NotFound);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_people() {
|
||||
test("/people/7f205202-7ba1-4c39-b2fc-3e630722bf9f", "We found: Lacy");
|
||||
test("/people/4da34121-bc7d-4fc1-aee6-bf8de0795333", "We found: Bob");
|
||||
test("/people/ad962969-4e3d-4de7-ac4a-2d86d6d10839", "We found: George");
|
||||
test("/people/e18b3a5c-488f-4159-a240-2101e0da19fd",
|
||||
"Person not found for UUID: e18b3a5c-488f-4159-a240-2101e0da19fd");
|
||||
test_404("/people/invalid_uuid");
|
||||
}
|
|
@ -89,6 +89,7 @@ function test_core() {
|
|||
tls
|
||||
json
|
||||
msgpack
|
||||
uuid
|
||||
)
|
||||
|
||||
pushd "${CORE_LIB_ROOT}" > /dev/null 2>&1
|
||||
|
|
Loading…
Reference in New Issue