mirror of https://github.com/rwf2/Rocket.git
Modularize contrib.
This commit is contained in:
parent
28f2a33abd
commit
9cb031a47d
|
@ -11,46 +11,46 @@ keywords = ["rocket", "web", "framework", "contrib", "contributed"]
|
||||||
license = "MIT/Apache-2.0"
|
license = "MIT/Apache-2.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["json", "static_files"]
|
# Internal use only.
|
||||||
|
templates = ["serde", "serde_json", "glob"]
|
||||||
|
databases = ["r2d2", "rocket_contrib_codegen/database_attribute"]
|
||||||
|
|
||||||
|
# User-facing features.
|
||||||
|
default = ["json", "serve"]
|
||||||
json = ["serde", "serde_json"]
|
json = ["serde", "serde_json"]
|
||||||
msgpack = ["serde", "rmp-serde"]
|
msgpack = ["serde", "rmp-serde"]
|
||||||
tera_templates = ["tera", "templates"]
|
tera_templates = ["tera", "templates"]
|
||||||
handlebars_templates = ["handlebars", "templates"]
|
handlebars_templates = ["handlebars", "templates"]
|
||||||
static_files = []
|
serve = []
|
||||||
# Internal use only.
|
|
||||||
templates = ["serde", "serde_json", "glob"]
|
|
||||||
|
|
||||||
# Database pooling features.
|
# The barage of user-facing database features.
|
||||||
# Internal use only.
|
diesel_sqlite_pool = ["databases", "diesel/sqlite", "diesel/r2d2"]
|
||||||
database_pool_codegen = ["rocket_contrib_codegen", "rocket_contrib_codegen/database_attribute"]
|
diesel_postgres_pool = ["databases", "diesel/postgres", "diesel/r2d2"]
|
||||||
database_pool = ["r2d2", "database_pool_codegen"]
|
diesel_mysql_pool = ["databases", "diesel/mysql", "diesel/r2d2"]
|
||||||
# External features.
|
postgres_pool = ["databases", "postgres", "r2d2_postgres"]
|
||||||
diesel_postgres_pool = ["database_pool", "diesel/postgres", "diesel/r2d2"]
|
mysql_pool = ["databases", "mysql", "r2d2_mysql"]
|
||||||
diesel_sqlite_pool = ["database_pool", "diesel/sqlite", "diesel/r2d2"]
|
sqlite_pool = ["databases", "rusqlite", "r2d2_sqlite"]
|
||||||
diesel_mysql_pool = ["database_pool", "diesel/mysql", "diesel/r2d2"]
|
cypher_pool = ["databases", "rusted_cypher", "r2d2_cypher"]
|
||||||
postgres_pool = ["database_pool", "postgres", "r2d2_postgres"]
|
redis_pool = ["databases", "redis", "r2d2_redis"]
|
||||||
mysql_pool = ["database_pool", "mysql", "r2d2_mysql"]
|
|
||||||
sqlite_pool = ["database_pool", "rusqlite", "r2d2_sqlite"]
|
|
||||||
cypher_pool = ["database_pool", "rusted_cypher", "r2d2_cypher"]
|
|
||||||
redis_pool = ["database_pool", "redis", "r2d2_redis"]
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
# Global dependencies.
|
||||||
rocket = { version = "0.4.0-dev", path = "../../core/lib/" }
|
rocket = { version = "0.4.0-dev", path = "../../core/lib/" }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
|
||||||
# UUID dependencies.
|
|
||||||
uuid = { version = "0.7", optional = true }
|
|
||||||
|
|
||||||
# Serialization and templating dependencies.
|
# Serialization and templating dependencies.
|
||||||
serde = { version = "1.0", optional = true }
|
serde = { version = "1.0", optional = true }
|
||||||
serde_json = { version = "1.0.26", optional = true }
|
serde_json = { version = "1.0.26", optional = true }
|
||||||
rmp-serde = { version = "^0.13", optional = true }
|
rmp-serde = { version = "^0.13", optional = true }
|
||||||
|
|
||||||
# Templating dependencies only.
|
# Templating dependencies.
|
||||||
handlebars = { version = "1.0", optional = true }
|
handlebars = { version = "1.0", optional = true }
|
||||||
glob = { version = "0.2", optional = true }
|
glob = { version = "0.2", optional = true }
|
||||||
tera = { version = "0.11", optional = true }
|
tera = { version = "0.11", optional = true }
|
||||||
|
|
||||||
|
# UUID dependencies.
|
||||||
|
uuid = { version = "0.7", optional = true }
|
||||||
|
|
||||||
# Database dependencies
|
# Database dependencies
|
||||||
diesel = { version = "1.0", default-features = false, optional = true }
|
diesel = { version = "1.0", default-features = false, optional = true }
|
||||||
postgres = { version = "0.15", optional = true }
|
postgres = { version = "0.15", optional = true }
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#![doc(cfg(feature = "diesel_sqlite_pool"))]
|
|
||||||
//! Traits, utilities, and a macro for easy database connection pooling.
|
//! Traits, utilities, and a macro for easy database connection pooling.
|
||||||
//!
|
//!
|
||||||
//! # Overview
|
//! # Overview
|
||||||
|
@ -351,50 +350,41 @@
|
||||||
//! implementing the [`Poolable`] trait. See the documentation for [`Poolable`]
|
//! implementing the [`Poolable`] trait. See the documentation for [`Poolable`]
|
||||||
//! for more details on how to implement it.
|
//! for more details on how to implement it.
|
||||||
//!
|
//!
|
||||||
//! [`FromRequest`]: rocket::FromRequest
|
//! [`FromRequest`]: rocket::request::FromRequest
|
||||||
//! [request guards]: rocket::FromRequest
|
//! [request guards]: rocket::request::FromRequest
|
||||||
//! [`Poolable`]: databases::Poolable
|
//! [`Poolable`]: databases::Poolable
|
||||||
|
|
||||||
pub extern crate r2d2;
|
pub extern crate r2d2;
|
||||||
|
|
||||||
|
#[cfg(any(feature = "diesel_sqlite_pool",
|
||||||
|
feature = "diesel_postgres_pool",
|
||||||
|
feature = "diesel_mysql_pool"))]
|
||||||
|
pub extern crate diesel;
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::fmt::{self, Display, Formatter};
|
use std::fmt::{self, Display, Formatter};
|
||||||
use std::marker::{Send, Sized};
|
use std::marker::{Send, Sized};
|
||||||
|
|
||||||
use rocket::config::{self, Value};
|
use rocket::config::{self, Value};
|
||||||
|
|
||||||
#[doc(inline)]
|
|
||||||
pub use rocket_contrib_codegen::database;
|
|
||||||
|
|
||||||
use self::r2d2::ManageConnection;
|
use self::r2d2::ManageConnection;
|
||||||
|
|
||||||
#[cfg(any(feature = "diesel_sqlite_pool", feature = "diesel_postgres_pool", feature = "diesel_mysql_pool"))]
|
#[doc(hidden)] pub use rocket_contrib_codegen::*;
|
||||||
pub extern crate diesel;
|
|
||||||
|
|
||||||
#[cfg(feature = "postgres_pool")]
|
#[cfg(feature = "postgres_pool")] pub extern crate postgres;
|
||||||
pub extern crate postgres;
|
#[cfg(feature = "postgres_pool")] pub extern crate r2d2_postgres;
|
||||||
#[cfg(feature = "postgres_pool")]
|
|
||||||
pub extern crate r2d2_postgres;
|
|
||||||
|
|
||||||
#[cfg(feature = "mysql_pool")]
|
#[cfg(feature = "mysql_pool")] pub extern crate mysql;
|
||||||
pub extern crate mysql;
|
#[cfg(feature = "mysql_pool")] pub extern crate r2d2_mysql;
|
||||||
#[cfg(feature = "mysql_pool")]
|
|
||||||
pub extern crate r2d2_mysql;
|
|
||||||
|
|
||||||
#[cfg(feature = "sqlite_pool")]
|
#[cfg(feature = "sqlite_pool")] pub extern crate rusqlite;
|
||||||
pub extern crate rusqlite;
|
#[cfg(feature = "sqlite_pool")] pub extern crate r2d2_sqlite;
|
||||||
#[cfg(feature = "sqlite_pool")]
|
|
||||||
pub extern crate r2d2_sqlite;
|
|
||||||
|
|
||||||
#[cfg(feature = "cypher_pool")]
|
#[cfg(feature = "cypher_pool")] pub extern crate rusted_cypher;
|
||||||
pub extern crate rusted_cypher;
|
#[cfg(feature = "cypher_pool")] pub extern crate r2d2_cypher;
|
||||||
#[cfg(feature = "cypher_pool")]
|
|
||||||
pub extern crate r2d2_cypher;
|
|
||||||
|
|
||||||
#[cfg(feature = "redis_pool")]
|
#[cfg(feature = "redis_pool")] pub extern crate redis;
|
||||||
pub extern crate redis;
|
#[cfg(feature = "redis_pool")] pub extern crate r2d2_redis;
|
||||||
#[cfg(feature = "redis_pool")]
|
|
||||||
pub extern crate r2d2_redis;
|
|
||||||
|
|
||||||
/// A structure representing a particular database configuration.
|
/// A structure representing a particular database configuration.
|
||||||
///
|
///
|
||||||
|
@ -447,14 +437,14 @@ pub enum DbError<T> {
|
||||||
|
|
||||||
/// Error returned on invalid database configurations.
|
/// Error returned on invalid database configurations.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum DatabaseConfigError {
|
pub enum ConfigError {
|
||||||
/// The `databases` configuration key is missing or is empty.
|
/// The `databases` configuration key is missing or is empty.
|
||||||
MissingTable,
|
MissingTable,
|
||||||
/// The requested database configuration key is missing from the active
|
/// The requested database configuration key is missing from the active
|
||||||
/// configuration.
|
/// configuration.
|
||||||
MissingKey,
|
MissingKey,
|
||||||
/// The configuration associated with the key isn't a
|
/// The configuration associated with the key isn't a
|
||||||
/// [Table](::rocket::config::Table).
|
/// [`Table`](::rocket::config::Table).
|
||||||
MalformedConfiguration,
|
MalformedConfiguration,
|
||||||
/// The required `url` key is missing.
|
/// The required `url` key is missing.
|
||||||
MissingUrl,
|
MissingUrl,
|
||||||
|
@ -488,7 +478,7 @@ pub enum DatabaseConfigError {
|
||||||
/// #
|
/// #
|
||||||
/// # use std::{collections::BTreeMap, mem::drop};
|
/// # use std::{collections::BTreeMap, mem::drop};
|
||||||
/// # use rocket::{fairing::AdHoc, config::{Config, Environment, Value}};
|
/// # use rocket::{fairing::AdHoc, config::{Config, Environment, Value}};
|
||||||
/// use rocket_contrib::databases::{database_config, DatabaseConfigError};
|
/// use rocket_contrib::databases::{database_config, ConfigError};
|
||||||
///
|
///
|
||||||
/// # let mut databases = BTreeMap::new();
|
/// # let mut databases = BTreeMap::new();
|
||||||
/// #
|
/// #
|
||||||
|
@ -517,7 +507,7 @@ pub enum DatabaseConfigError {
|
||||||
/// assert_eq!(other_config.url, "mysql://root:root@localhost/database");
|
/// assert_eq!(other_config.url, "mysql://root:root@localhost/database");
|
||||||
///
|
///
|
||||||
/// let error = database_config("invalid_db", rocket.config()).unwrap_err();
|
/// let error = database_config("invalid_db", rocket.config()).unwrap_err();
|
||||||
/// assert_eq!(error, DatabaseConfigError::MissingKey);
|
/// assert_eq!(error, ConfigError::MissingKey);
|
||||||
/// # }
|
/// # }
|
||||||
/// #
|
/// #
|
||||||
/// # Ok(rocket)
|
/// # Ok(rocket)
|
||||||
|
@ -526,27 +516,27 @@ pub enum DatabaseConfigError {
|
||||||
pub fn database_config<'a>(
|
pub fn database_config<'a>(
|
||||||
name: &str,
|
name: &str,
|
||||||
from: &'a config::Config
|
from: &'a config::Config
|
||||||
) -> Result<DatabaseConfig<'a>, DatabaseConfigError> {
|
) -> Result<DatabaseConfig<'a>, ConfigError> {
|
||||||
// Find the first `databases` config that's a table with a key of 'name'
|
// Find the first `databases` config that's a table with a key of 'name'
|
||||||
// equal to `name`.
|
// equal to `name`.
|
||||||
let connection_config = from.get_table("databases")
|
let connection_config = from.get_table("databases")
|
||||||
.map_err(|_| DatabaseConfigError::MissingTable)?
|
.map_err(|_| ConfigError::MissingTable)?
|
||||||
.get(name)
|
.get(name)
|
||||||
.ok_or(DatabaseConfigError::MissingKey)?
|
.ok_or(ConfigError::MissingKey)?
|
||||||
.as_table()
|
.as_table()
|
||||||
.ok_or(DatabaseConfigError::MalformedConfiguration)?;
|
.ok_or(ConfigError::MalformedConfiguration)?;
|
||||||
|
|
||||||
let maybe_url = connection_config.get("url")
|
let maybe_url = connection_config.get("url")
|
||||||
.ok_or(DatabaseConfigError::MissingUrl)?;
|
.ok_or(ConfigError::MissingUrl)?;
|
||||||
|
|
||||||
let url = maybe_url.as_str().ok_or(DatabaseConfigError::MalformedUrl)?;
|
let url = maybe_url.as_str().ok_or(ConfigError::MalformedUrl)?;
|
||||||
|
|
||||||
let pool_size = connection_config.get("pool_size")
|
let pool_size = connection_config.get("pool_size")
|
||||||
.and_then(Value::as_integer)
|
.and_then(Value::as_integer)
|
||||||
.unwrap_or(from.workers as i64);
|
.unwrap_or(from.workers as i64);
|
||||||
|
|
||||||
if pool_size < 1 || pool_size > u32::max_value() as i64 {
|
if pool_size < 1 || pool_size > u32::max_value() as i64 {
|
||||||
return Err(DatabaseConfigError::InvalidPoolSize(pool_size));
|
return Err(ConfigError::InvalidPoolSize(pool_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut extras = connection_config.clone();
|
let mut extras = connection_config.clone();
|
||||||
|
@ -556,25 +546,25 @@ pub fn database_config<'a>(
|
||||||
Ok(DatabaseConfig { url, pool_size: pool_size as u32, extras: extras })
|
Ok(DatabaseConfig { url, pool_size: pool_size as u32, extras: extras })
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Display for DatabaseConfigError {
|
impl<'a> Display for ConfigError {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
DatabaseConfigError::MissingTable => {
|
ConfigError::MissingTable => {
|
||||||
write!(f, "A table named `databases` was not found for this configuration")
|
write!(f, "A table named `databases` was not found for this configuration")
|
||||||
},
|
},
|
||||||
DatabaseConfigError::MissingKey => {
|
ConfigError::MissingKey => {
|
||||||
write!(f, "An entry in the `databases` table was not found for this key")
|
write!(f, "An entry in the `databases` table was not found for this key")
|
||||||
},
|
},
|
||||||
DatabaseConfigError::MalformedConfiguration => {
|
ConfigError::MalformedConfiguration => {
|
||||||
write!(f, "The configuration for this database is malformed")
|
write!(f, "The configuration for this database is malformed")
|
||||||
}
|
}
|
||||||
DatabaseConfigError::MissingUrl => {
|
ConfigError::MissingUrl => {
|
||||||
write!(f, "The connection URL is missing for this database")
|
write!(f, "The connection URL is missing for this database")
|
||||||
},
|
},
|
||||||
DatabaseConfigError::MalformedUrl => {
|
ConfigError::MalformedUrl => {
|
||||||
write!(f, "The specified connection URL is malformed")
|
write!(f, "The specified connection URL is malformed")
|
||||||
},
|
},
|
||||||
DatabaseConfigError::InvalidPoolSize(invalid_size) => {
|
ConfigError::InvalidPoolSize(invalid_size) => {
|
||||||
write!(f, "'{}' is not a valid value for `pool_size`", invalid_size)
|
write!(f, "'{}' is not a valid value for `pool_size`", invalid_size)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -782,7 +772,7 @@ impl Poolable for redis::Connection {
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use rocket::{Config, config::{Environment, Value}};
|
use rocket::{Config, config::{Environment, Value}};
|
||||||
use super::{DatabaseConfigError::*, database_config};
|
use super::{ConfigError::*, database_config};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn no_database_entry_in_config_returns_error() {
|
fn no_database_entry_in_config_returns_error() {
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
extern crate serde;
|
||||||
|
extern crate serde_json;
|
||||||
|
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::io::{self, Read};
|
use std::io::{self, Read};
|
||||||
|
|
||||||
|
@ -7,25 +10,32 @@ use rocket::data::{Outcome, Transform, Transform::*, Transformed, Data, FromData
|
||||||
use rocket::response::{self, Responder, content};
|
use rocket::response::{self, Responder, content};
|
||||||
use rocket::http::Status;
|
use rocket::http::Status;
|
||||||
|
|
||||||
use serde::{Serialize, Serializer};
|
use self::serde::{Serialize, Serializer};
|
||||||
use serde::de::{Deserialize, Deserializer};
|
use self::serde::de::{Deserialize, Deserializer};
|
||||||
use serde_json;
|
|
||||||
|
|
||||||
/// The JSON type: implements `FromData` and `Responder`, allowing you to easily
|
#[doc(hidden)]
|
||||||
/// consume and respond with JSON.
|
pub use self::serde_json::{json_internal, json_internal_vec};
|
||||||
|
|
||||||
|
/// The JSON type: implements [`FromData`] and [`Responder`], allowing you to
|
||||||
|
/// easily consume and respond with JSON.
|
||||||
///
|
///
|
||||||
/// ## Receiving JSON
|
/// ## Receiving JSON
|
||||||
///
|
///
|
||||||
/// If you're receiving JSON data, simply add a `data` parameter to your route
|
/// If you're receiving JSON data, simply add a `data` parameter to your route
|
||||||
/// arguments and ensure the type of the parameter is a `Json<T>`, where `T` is
|
/// arguments and ensure the type of the parameter is a `Json<T>`, where `T` is
|
||||||
/// some type you'd like to parse from JSON. `T` must implement `Deserialize` or
|
/// some type you'd like to parse from JSON. `T` must implement [`Deserialize`]
|
||||||
/// `DeserializeOwned` from [`serde`](https://github.com/serde-rs/json). The
|
/// or from [`serde`]. The data is parsed from the HTTP request body.
|
||||||
/// data is parsed from the HTTP request body.
|
|
||||||
///
|
///
|
||||||
/// ```rust,ignore
|
/// ```rust
|
||||||
/// #[post("/users/", format = "json", data = "<user>")]
|
/// # #![feature(proc_macro_hygiene, decl_macro)]
|
||||||
|
/// # #[macro_use] extern crate rocket;
|
||||||
|
/// # extern crate rocket_contrib;
|
||||||
|
/// # type User = usize;
|
||||||
|
/// use rocket_contrib::json::Json;
|
||||||
|
///
|
||||||
|
/// #[post("/users", format = "json", data = "<user>")]
|
||||||
/// fn new_user(user: Json<User>) {
|
/// fn new_user(user: Json<User>) {
|
||||||
/// ...
|
/// /* ... */
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
@ -37,14 +47,20 @@ use serde_json;
|
||||||
/// ## Sending JSON
|
/// ## Sending JSON
|
||||||
///
|
///
|
||||||
/// If you're responding with JSON data, return a `Json<T>` type, where `T`
|
/// If you're responding with JSON data, return a `Json<T>` type, where `T`
|
||||||
/// implements `Serialize` from [Serde](https://github.com/serde-rs/json). The
|
/// implements [`Serialize`] from [`serde`]. The content type of the response is
|
||||||
/// content type of the response is set to `application/json` automatically.
|
/// set to `application/json` automatically.
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # #![feature(proc_macro_hygiene, decl_macro)]
|
||||||
|
/// # #[macro_use] extern crate rocket;
|
||||||
|
/// # extern crate rocket_contrib;
|
||||||
|
/// # type User = usize;
|
||||||
|
/// use rocket_contrib::json::Json;
|
||||||
///
|
///
|
||||||
/// ```rust,ignore
|
|
||||||
/// #[get("/users/<id>")]
|
/// #[get("/users/<id>")]
|
||||||
/// fn user(id: usize) -> Json<User> {
|
/// fn user(id: usize) -> Json<User> {
|
||||||
/// let user_from_id = User::from(id);
|
/// let user_from_id = User::from(id);
|
||||||
/// ...
|
/// /* ... */
|
||||||
/// Json(user_from_id)
|
/// Json(user_from_id)
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -70,7 +86,7 @@ impl<T> Json<T> {
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use rocket_contrib::Json;
|
/// # use rocket_contrib::json::Json;
|
||||||
/// let string = "Hello".to_string();
|
/// let string = "Hello".to_string();
|
||||||
/// let my_json = Json(string);
|
/// let my_json = Json(string);
|
||||||
/// assert_eq!(my_json.into_inner(), "Hello".to_string());
|
/// assert_eq!(my_json.into_inner(), "Hello".to_string());
|
||||||
|
@ -183,7 +199,7 @@ impl<T> DerefMut for Json<T> {
|
||||||
/// # #![feature(proc_macro_hygiene, decl_macro)]
|
/// # #![feature(proc_macro_hygiene, decl_macro)]
|
||||||
/// # #[macro_use] extern crate rocket;
|
/// # #[macro_use] extern crate rocket;
|
||||||
/// # #[macro_use] extern crate rocket_contrib;
|
/// # #[macro_use] extern crate rocket_contrib;
|
||||||
/// use rocket_contrib::JsonValue;
|
/// use rocket_contrib::json::JsonValue;
|
||||||
///
|
///
|
||||||
/// #[get("/json")]
|
/// #[get("/json")]
|
||||||
/// fn get_json() -> JsonValue {
|
/// fn get_json() -> JsonValue {
|
||||||
|
@ -265,14 +281,14 @@ impl<'a> Responder<'a> for JsonValue {
|
||||||
/// #[macro_use] extern crate rocket_contrib;
|
/// #[macro_use] extern crate rocket_contrib;
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// The return type of a `json!` invocation is [`JsonValue`]. A value created
|
/// The return type of a `json!` invocation is [`JsonValue`](json::JsonValue). A
|
||||||
/// with this macro can be returned from a handler as follows:
|
/// value created with this macro can be returned from a handler as follows:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(proc_macro_hygiene, decl_macro)]
|
/// # #![feature(proc_macro_hygiene, decl_macro)]
|
||||||
/// # #[macro_use] extern crate rocket;
|
/// # #[macro_use] extern crate rocket;
|
||||||
/// # #[macro_use] extern crate rocket_contrib;
|
/// # #[macro_use] extern crate rocket_contrib;
|
||||||
/// use rocket_contrib::JsonValue;
|
/// use rocket_contrib::json::JsonValue;
|
||||||
///
|
///
|
||||||
/// #[get("/json")]
|
/// #[get("/json")]
|
||||||
/// fn get_json() -> JsonValue {
|
/// fn get_json() -> JsonValue {
|
||||||
|
@ -283,9 +299,9 @@ impl<'a> Responder<'a> for JsonValue {
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// The `Responder` implementation for `JsonValue` serializes the value into a
|
/// The [`Responder`](rocket::response::Responder) implementation for
|
||||||
/// JSON string and sets it as the body of the response with a `Content-Type` of
|
/// `JsonValue` serializes the value into a JSON string and sets it as the body
|
||||||
/// `application/json`.
|
/// of the response with a `Content-Type` of `application/json`.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -358,6 +374,6 @@ impl<'a> Responder<'a> for JsonValue {
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! json {
|
macro_rules! json {
|
||||||
($($json:tt)+) => {
|
($($json:tt)+) => {
|
||||||
$crate::JsonValue(json_internal!($($json)+))
|
$crate::json::JsonValue($crate::json::json_internal!($($json)+))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,13 +16,13 @@
|
||||||
//! common modules exposed by default. The present feature list is below, with
|
//! common modules exposed by default. The present feature list is below, with
|
||||||
//! an asterisk next to the features that are enabled by default:
|
//! an asterisk next to the features that are enabled by default:
|
||||||
//!
|
//!
|
||||||
//! * [json*](Json)
|
//! * [json*](type@json) - JSON (de)serialization
|
||||||
//! * [static_files*](static_files)
|
//! * [serve*](serve) - Static File Serving
|
||||||
//! * [msgpack](MsgPack)
|
//! * [msgpack](msgpack) - MessagePack (de)serialization
|
||||||
//! * [handlebars_templates](Template)
|
//! * [handlebars_templates](templates) - Handlebars Templating
|
||||||
//! * [tera_templates](Template)
|
//! * [tera_templates](templates) - Tera Templating
|
||||||
//! * [uuid](Uuid)
|
//! * [uuid](uuid) - UUID (de)serialization
|
||||||
//! * [${database}_pool](databases)
|
//! * [${database}_pool](databases) - Database Configuration and Pooling
|
||||||
//!
|
//!
|
||||||
//! The recommend way to include features from this crate via Cargo in your
|
//! The recommend way to include features from this crate via Cargo in your
|
||||||
//! project is by adding a `[dependencies.rocket_contrib]` section to your
|
//! project is by adding a `[dependencies.rocket_contrib]` section to your
|
||||||
|
@ -42,59 +42,14 @@
|
||||||
#[allow(unused_imports)] #[macro_use] extern crate log;
|
#[allow(unused_imports)] #[macro_use] extern crate log;
|
||||||
#[allow(unused_imports)] #[macro_use] extern crate rocket;
|
#[allow(unused_imports)] #[macro_use] extern crate rocket;
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature="json")] #[macro_use] pub mod json;
|
||||||
extern crate serde;
|
#[cfg(feature="serve")] pub mod serve;
|
||||||
|
#[cfg(feature="msgpack")] pub mod msgpack;
|
||||||
|
#[cfg(feature="templates")] pub mod templates;
|
||||||
|
#[cfg(feature="uuid")] pub mod uuid;
|
||||||
|
#[cfg(feature="databases")] pub mod databases;
|
||||||
|
|
||||||
#[cfg(feature = "json")]
|
|
||||||
extern crate serde_json;
|
|
||||||
|
|
||||||
#[cfg(feature = "json")]
|
|
||||||
pub use serde_json::{json_internal, json_internal_vec};
|
|
||||||
|
|
||||||
#[cfg(feature = "handlebars_templates")]
|
|
||||||
pub extern crate handlebars;
|
|
||||||
|
|
||||||
#[cfg(feature = "tera_templates")]
|
|
||||||
pub extern crate tera;
|
|
||||||
|
|
||||||
#[cfg(feature = "json")]
|
|
||||||
#[cfg_attr(feature = "json", macro_use)]
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub mod json;
|
|
||||||
|
|
||||||
#[cfg(feature = "json")]
|
|
||||||
pub use json::{Json, JsonError, JsonValue};
|
|
||||||
|
|
||||||
#[cfg(feature = "msgpack")]
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub mod msgpack;
|
|
||||||
|
|
||||||
#[cfg(feature = "msgpack")]
|
|
||||||
pub use msgpack::{MsgPack, MsgPackError};
|
|
||||||
|
|
||||||
#[cfg(feature = "templates")]
|
|
||||||
mod templates;
|
|
||||||
|
|
||||||
#[cfg(feature = "templates")]
|
|
||||||
pub use templates::{Engines, Template, TemplateMetadata};
|
|
||||||
|
|
||||||
#[cfg(feature = "uuid")]
|
|
||||||
mod uuid;
|
|
||||||
|
|
||||||
#[cfg(feature = "uuid")]
|
|
||||||
pub use uuid::{Uuid, UuidParseError};
|
|
||||||
|
|
||||||
#[cfg(feature = "static_files")]
|
|
||||||
pub mod static_files;
|
|
||||||
|
|
||||||
#[cfg(feature = "database_pool")]
|
|
||||||
pub mod databases;
|
|
||||||
|
|
||||||
#[cfg(feature = "database_pool_codegen")]
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
#[cfg(feature="databases")]
|
||||||
extern crate rocket_contrib_codegen;
|
extern crate rocket_contrib_codegen;
|
||||||
|
|
||||||
#[cfg(feature = "database_pool_codegen")]
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub use rocket_contrib_codegen::*;
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
extern crate serde;
|
||||||
extern crate rmp_serde;
|
extern crate rmp_serde;
|
||||||
|
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
@ -9,31 +10,28 @@ use rocket::data::{Outcome, Transform, Transform::*, Transformed, Data, FromData
|
||||||
use rocket::response::{self, Responder, Response};
|
use rocket::response::{self, Responder, Response};
|
||||||
use rocket::http::Status;
|
use rocket::http::Status;
|
||||||
|
|
||||||
use serde::Serialize;
|
use self::serde::Serialize;
|
||||||
use serde::de::Deserialize;
|
use self::serde::de::Deserialize;
|
||||||
|
|
||||||
pub use self::rmp_serde::decode::Error as MsgPackError;
|
pub use self::rmp_serde::decode::Error;
|
||||||
|
|
||||||
/// The `MsgPack` type: implements `FromData` and `Responder`, allowing you to
|
/// The `MsgPack` type: implements [`FromData`] and [`Responder`], allowing you
|
||||||
/// easily consume and respond with MessagePack data.
|
/// to easily consume and respond with MessagePack data.
|
||||||
///
|
///
|
||||||
/// ## Receiving MessagePack
|
/// ## Receiving MessagePack
|
||||||
///
|
///
|
||||||
/// If you're receiving MessagePack data, simply add a `data` parameter to your
|
/// If you're receiving MessagePack data, simply add a `data` parameter to your
|
||||||
/// route arguments and ensure the type of the parameter is a `MsgPack<T>`,
|
/// route arguments and ensure the type of the parameter is a `MsgPack<T>`,
|
||||||
/// where `T` is some type you'd like to parse from MessagePack. `T` must
|
/// where `T` is some type you'd like to parse from MessagePack. `T` must
|
||||||
/// implement `Deserialize` or `DeserializeOwned` from
|
/// implement [`Deserialize`] from [`serde`]. The data is parsed from the HTTP
|
||||||
/// [`serde`](https://github.com/serde-rs/serde). The data is parsed from the
|
/// request body.
|
||||||
/// HTTP request body.
|
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(proc_macro_hygiene, decl_macro)]
|
/// # #![feature(proc_macro_hygiene, decl_macro)]
|
||||||
/// # #[macro_use] extern crate rocket;
|
/// # #[macro_use] extern crate rocket;
|
||||||
/// # extern crate rocket_contrib;
|
/// # extern crate rocket_contrib;
|
||||||
/// # type User = usize;
|
/// # type User = usize;
|
||||||
/// # fn main() { }
|
/// use rocket_contrib::msgpack::MsgPack;
|
||||||
/// #
|
|
||||||
/// use rocket_contrib::MsgPack;
|
|
||||||
///
|
///
|
||||||
/// #[post("/users", format = "msgpack", data = "<user>")]
|
/// #[post("/users", format = "msgpack", data = "<user>")]
|
||||||
/// fn new_user(user: MsgPack<User>) {
|
/// fn new_user(user: MsgPack<User>) {
|
||||||
|
@ -49,18 +47,15 @@ pub use self::rmp_serde::decode::Error as MsgPackError;
|
||||||
/// ## Sending MessagePack
|
/// ## Sending MessagePack
|
||||||
///
|
///
|
||||||
/// If you're responding with MessagePack data, return a `MsgPack<T>` type,
|
/// If you're responding with MessagePack data, return a `MsgPack<T>` type,
|
||||||
/// where `T` implements `Serialize` from
|
/// where `T` implements [`Serialize`] from [`serde`]. The content type of the
|
||||||
/// [serde](https://github.com/serde-rs/serde). The content type of the response
|
/// response is set to `application/msgpack` automatically.
|
||||||
/// is set to `application/msgpack` automatically.
|
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(proc_macro_hygiene, decl_macro)]
|
/// # #![feature(proc_macro_hygiene, decl_macro)]
|
||||||
/// # #[macro_use] extern crate rocket;
|
/// # #[macro_use] extern crate rocket;
|
||||||
/// # extern crate rocket_contrib;
|
/// # extern crate rocket_contrib;
|
||||||
/// # type User = usize;
|
/// # type User = usize;
|
||||||
/// # fn main() { }
|
/// use rocket_contrib::msgpack::MsgPack;
|
||||||
/// #
|
|
||||||
/// use rocket_contrib::MsgPack;
|
|
||||||
///
|
///
|
||||||
/// #[get("/users/<id>")]
|
/// #[get("/users/<id>")]
|
||||||
/// fn user(id: usize) -> MsgPack<User> {
|
/// fn user(id: usize) -> MsgPack<User> {
|
||||||
|
@ -92,7 +87,7 @@ impl<T> MsgPack<T> {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # use rocket_contrib::MsgPack;
|
/// # use rocket_contrib::msgpack::MsgPack;
|
||||||
/// let string = "Hello".to_string();
|
/// let string = "Hello".to_string();
|
||||||
/// let my_msgpack = MsgPack(string);
|
/// let my_msgpack = MsgPack(string);
|
||||||
/// assert_eq!(my_msgpack.into_inner(), "Hello".to_string());
|
/// assert_eq!(my_msgpack.into_inner(), "Hello".to_string());
|
||||||
|
@ -107,7 +102,7 @@ impl<T> MsgPack<T> {
|
||||||
const LIMIT: u64 = 1 << 20;
|
const LIMIT: u64 = 1 << 20;
|
||||||
|
|
||||||
impl<'a, T: Deserialize<'a>> FromData<'a> for MsgPack<T> {
|
impl<'a, T: Deserialize<'a>> FromData<'a> for MsgPack<T> {
|
||||||
type Error = MsgPackError;
|
type Error = Error;
|
||||||
type Owned = Vec<u8>;
|
type Owned = Vec<u8>;
|
||||||
type Borrowed = [u8];
|
type Borrowed = [u8];
|
||||||
|
|
||||||
|
@ -116,12 +111,12 @@ impl<'a, T: Deserialize<'a>> FromData<'a> for MsgPack<T> {
|
||||||
let size_limit = r.limits().get("msgpack").unwrap_or(LIMIT);
|
let size_limit = r.limits().get("msgpack").unwrap_or(LIMIT);
|
||||||
match d.open().take(size_limit).read_to_end(&mut buf) {
|
match d.open().take(size_limit).read_to_end(&mut buf) {
|
||||||
Ok(_) => Borrowed(Success(buf)),
|
Ok(_) => Borrowed(Success(buf)),
|
||||||
Err(e) => Borrowed(Failure((Status::BadRequest, MsgPackError::InvalidDataRead(e))))
|
Err(e) => Borrowed(Failure((Status::BadRequest, Error::InvalidDataRead(e))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_data(_: &Request, o: Transformed<'a, Self>) -> Outcome<Self, Self::Error> {
|
fn from_data(_: &Request, o: Transformed<'a, Self>) -> Outcome<Self, Self::Error> {
|
||||||
use self::MsgPackError::*;
|
use self::Error::*;
|
||||||
|
|
||||||
let buf = o.borrowed()?;
|
let buf = o.borrowed()?;
|
||||||
match rmp_serde::from_slice(&buf) {
|
match rmp_serde::from_slice(&buf) {
|
||||||
|
|
|
@ -46,7 +46,7 @@ impl Options {
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use rocket_contrib::static_files::Options;
|
/// use rocket_contrib::serve::Options;
|
||||||
///
|
///
|
||||||
/// let index_request = Options::Index | Options::DotFiles;
|
/// let index_request = Options::Index | Options::DotFiles;
|
||||||
/// assert!(index_request.contains(Options::Index));
|
/// assert!(index_request.contains(Options::Index));
|
||||||
|
@ -96,7 +96,7 @@ impl ::std::ops::BitOr for Options {
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
/// # extern crate rocket_contrib;
|
/// # extern crate rocket_contrib;
|
||||||
/// use rocket_contrib::static_files::StaticFiles;
|
/// use rocket_contrib::serve::StaticFiles;
|
||||||
///
|
///
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
/// # if false {
|
/// # if false {
|
||||||
|
@ -122,7 +122,7 @@ impl ::std::ops::BitOr for Options {
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
/// # extern crate rocket_contrib;
|
/// # extern crate rocket_contrib;
|
||||||
/// use rocket_contrib::static_files::StaticFiles;
|
/// use rocket_contrib::serve::StaticFiles;
|
||||||
///
|
///
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
/// # if false {
|
/// # if false {
|
||||||
|
@ -151,7 +151,7 @@ impl StaticFiles {
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
/// # extern crate rocket_contrib;
|
/// # extern crate rocket_contrib;
|
||||||
/// use rocket_contrib::static_files::StaticFiles;
|
/// use rocket_contrib::serve::StaticFiles;
|
||||||
///
|
///
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
/// # if false {
|
/// # if false {
|
||||||
|
@ -177,7 +177,7 @@ impl StaticFiles {
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # extern crate rocket;
|
/// # extern crate rocket;
|
||||||
/// # extern crate rocket_contrib;
|
/// # extern crate rocket_contrib;
|
||||||
/// use rocket_contrib::static_files::{StaticFiles, Options};
|
/// use rocket_contrib::serve::{StaticFiles, Options};
|
||||||
///
|
///
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
/// # if false {
|
/// # if false {
|
|
@ -1,18 +1,17 @@
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use super::{Engines, TemplateInfo};
|
use templates::{glob, Engines, TemplateInfo};
|
||||||
use super::glob;
|
|
||||||
|
|
||||||
use rocket::http::ContentType;
|
use rocket::http::ContentType;
|
||||||
|
|
||||||
pub struct Context {
|
crate struct Context {
|
||||||
/// The root of the template directory.
|
/// The root of the template directory.
|
||||||
pub root: PathBuf,
|
crate root: PathBuf,
|
||||||
/// Mapping from template name to its information.
|
/// Mapping from template name to its information.
|
||||||
pub templates: HashMap<String, TemplateInfo>,
|
crate templates: HashMap<String, TemplateInfo>,
|
||||||
/// Loaded template engines
|
/// Loaded template engines
|
||||||
pub engines: Engines,
|
crate engines: Engines,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
|
|
|
@ -1,19 +1,17 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use super::serde::Serialize;
|
use templates::{TemplateInfo, serde::Serialize};
|
||||||
use super::TemplateInfo;
|
|
||||||
|
|
||||||
#[cfg(feature = "tera_templates")] use super::tera_templates::Tera;
|
#[cfg(feature = "tera_templates")] use templates::tera::Tera;
|
||||||
#[cfg(feature = "handlebars_templates")] use super::handlebars_templates::Handlebars;
|
#[cfg(feature = "handlebars_templates")] use templates::handlebars::Handlebars;
|
||||||
|
|
||||||
pub trait Engine: Send + Sync + 'static {
|
crate trait Engine: Send + Sync + 'static {
|
||||||
const EXT: &'static str;
|
const EXT: &'static str;
|
||||||
|
|
||||||
fn init(templates: &[(&str, &TemplateInfo)]) -> Option<Self> where Self: Sized;
|
fn init(templates: &[(&str, &TemplateInfo)]) -> Option<Self> where Self: Sized;
|
||||||
fn render<C: Serialize>(&self, name: &str, context: C) -> Option<String>;
|
fn render<C: Serialize>(&self, name: &str, context: C) -> Option<String>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(cfg(feature = "tera_templates"))]
|
|
||||||
/// A structure exposing access to templating engines.
|
/// A structure exposing access to templating engines.
|
||||||
///
|
///
|
||||||
/// Calling methods on the exposed template engine types may require importing
|
/// Calling methods on the exposed template engine types may require importing
|
||||||
|
@ -21,13 +19,14 @@ pub trait Engine: Send + Sync + 'static {
|
||||||
/// imported from the reexported crate at the root of `rocket_contrib` to avoid
|
/// imported from the reexported crate at the root of `rocket_contrib` to avoid
|
||||||
/// version mismatches. For instance, when registering a Tera filter, the
|
/// version mismatches. For instance, when registering a Tera filter, the
|
||||||
/// [`tera::Value`] and [`tera::Result`] types are required. Import them from
|
/// [`tera::Value`] and [`tera::Result`] types are required. Import them from
|
||||||
/// `rocket_contrib::tera`. The example below illustrates this:
|
/// `rocket_contrib::templates::tera`. The example below illustrates this:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
|
/// # #[cfg(feature = "tera_templates")] {
|
||||||
/// use std::collections::HashMap;
|
/// use std::collections::HashMap;
|
||||||
///
|
///
|
||||||
/// use rocket_contrib::{Template, Engines};
|
/// use rocket_contrib::templates::{Template, Engines};
|
||||||
/// use rocket_contrib::tera::{self, Value};
|
/// use rocket_contrib::templates::tera::{self, Value};
|
||||||
///
|
///
|
||||||
/// fn my_filter(value: Value, _: HashMap<String, Value>) -> tera::Result<Value> {
|
/// fn my_filter(value: Value, _: HashMap<String, Value>) -> tera::Result<Value> {
|
||||||
/// # /*
|
/// # /*
|
||||||
|
@ -38,25 +37,22 @@ pub trait Engine: Send + Sync + 'static {
|
||||||
/// Template::custom(|engines: &mut Engines| {
|
/// Template::custom(|engines: &mut Engines| {
|
||||||
/// engines.tera.register_filter("my_filter", my_filter);
|
/// engines.tera.register_filter("my_filter", my_filter);
|
||||||
/// });
|
/// });
|
||||||
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// [`tera::Value`]: ::tera::Value
|
/// [`tera::Value`]: ::templates::tera::Value
|
||||||
/// [`tera::Result`]: ::tera::Result
|
/// [`tera::Result`]: ::templates::tera::Result
|
||||||
pub struct Engines {
|
pub struct Engines {
|
||||||
#[cfg(feature = "tera_templates")]
|
/// A `Tera` templating engine. This field is only available when the
|
||||||
/// A [`Tera`] structure. This field is only available when the
|
|
||||||
/// `tera_templates` feature is enabled. When calling methods on the `Tera`
|
/// `tera_templates` feature is enabled. When calling methods on the `Tera`
|
||||||
/// instance, ensure you use types imported from `rocket_contrib::tera` to
|
/// instance, ensure you use types imported from
|
||||||
/// avoid version mismatches.
|
/// `rocket_contrib::templates::tera` to avoid version mismatches.
|
||||||
///
|
#[cfg(feature = "tera_templates")]
|
||||||
/// [`Tera`]: tera::Tera
|
|
||||||
pub tera: Tera,
|
pub tera: Tera,
|
||||||
/// A [`Handlebars`] structure. This field is only available when the
|
/// The Handlebars templating engine. This field is only available when the
|
||||||
/// `handlebars_templates` feature is enabled. When calling methods on the
|
/// `handlebars_templates` feature is enabled. When calling methods on the
|
||||||
/// `Tera` instance, ensure you use types
|
/// `Tera` instance, ensure you use types imported from
|
||||||
/// imported from `rocket_contrib::handlebars` to avoid version mismatches.
|
/// `rocket_contrib::templates::handlebars` to avoid version mismatches.
|
||||||
///
|
|
||||||
/// [`Handlebars`]: handlebars::Handlebars
|
|
||||||
#[cfg(feature = "handlebars_templates")]
|
#[cfg(feature = "handlebars_templates")]
|
||||||
pub handlebars: Handlebars,
|
pub handlebars: Handlebars,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +1,26 @@
|
||||||
use super::DEFAULT_TEMPLATE_DIR;
|
use templates::{DEFAULT_TEMPLATE_DIR, Context, Engines};
|
||||||
use super::context::Context;
|
|
||||||
use super::engine::Engines;
|
|
||||||
|
|
||||||
use rocket::Rocket;
|
use rocket::Rocket;
|
||||||
use rocket::config::ConfigError;
|
use rocket::config::ConfigError;
|
||||||
use rocket::fairing::{Fairing, Info, Kind};
|
use rocket::fairing::{Fairing, Info, Kind};
|
||||||
|
|
||||||
pub use self::context::ContextManager;
|
crate use self::context::ContextManager;
|
||||||
|
|
||||||
#[cfg(not(debug_assertions))]
|
#[cfg(not(debug_assertions))]
|
||||||
mod context {
|
mod context {
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use super::Context;
|
use templates::Context;
|
||||||
|
|
||||||
/// Wraps a Context. With `cfg(debug_assertions)` active, this structure
|
/// Wraps a Context. With `cfg(debug_assertions)` active, this structure
|
||||||
/// additionally provides a method to reload the context at runtime.
|
/// additionally provides a method to reload the context at runtime.
|
||||||
pub struct ContextManager(Context);
|
crate struct ContextManager(Context);
|
||||||
|
|
||||||
impl ContextManager {
|
impl ContextManager {
|
||||||
pub fn new(ctxt: Context) -> ContextManager {
|
crate fn new(ctxt: Context) -> ContextManager {
|
||||||
ContextManager(ctxt)
|
ContextManager(ctxt)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn context<'a>(&'a self) -> impl Deref<Target=Context> + 'a {
|
crate fn context<'a>(&'a self) -> impl Deref<Target=Context> + 'a {
|
||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,13 +34,13 @@ mod context {
|
||||||
use std::sync::{RwLock, Mutex};
|
use std::sync::{RwLock, Mutex};
|
||||||
use std::sync::mpsc::{channel, Receiver};
|
use std::sync::mpsc::{channel, Receiver};
|
||||||
|
|
||||||
use super::{Context, Engines};
|
use templates::{Context, Engines};
|
||||||
|
|
||||||
use self::notify::{raw_watcher, RawEvent, RecommendedWatcher, RecursiveMode, Watcher};
|
use self::notify::{raw_watcher, RawEvent, RecommendedWatcher, RecursiveMode, Watcher};
|
||||||
|
|
||||||
/// Wraps a Context. With `cfg(debug_assertions)` active, this structure
|
/// Wraps a Context. With `cfg(debug_assertions)` active, this structure
|
||||||
/// additionally provides a method to reload the context at runtime.
|
/// additionally provides a method to reload the context at runtime.
|
||||||
pub struct ContextManager {
|
crate struct ContextManager {
|
||||||
/// The current template context, inside an RwLock so it can be updated.
|
/// The current template context, inside an RwLock so it can be updated.
|
||||||
context: RwLock<Context>,
|
context: RwLock<Context>,
|
||||||
/// A filesystem watcher and the receive queue for its events.
|
/// A filesystem watcher and the receive queue for its events.
|
||||||
|
@ -50,7 +48,7 @@ mod context {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ContextManager {
|
impl ContextManager {
|
||||||
pub fn new(ctxt: Context) -> ContextManager {
|
crate fn new(ctxt: Context) -> ContextManager {
|
||||||
let (tx, rx) = channel();
|
let (tx, rx) = channel();
|
||||||
|
|
||||||
let watcher = if let Ok(mut watcher) = raw_watcher(tx) {
|
let watcher = if let Ok(mut watcher) = raw_watcher(tx) {
|
||||||
|
@ -73,7 +71,7 @@ mod context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn context<'a>(&'a self) -> impl Deref<Target=Context> + 'a {
|
crate fn context<'a>(&'a self) -> impl Deref<Target=Context> + 'a {
|
||||||
self.context.read().unwrap()
|
self.context.read().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +83,7 @@ mod context {
|
||||||
/// have been changes since the last reload, all templates are
|
/// have been changes since the last reload, all templates are
|
||||||
/// reinitialized from disk and the user's customization callback is run
|
/// reinitialized from disk and the user's customization callback is run
|
||||||
/// again.
|
/// again.
|
||||||
pub fn reload_if_needed<F: Fn(&mut Engines)>(&self, custom_callback: F) {
|
crate fn reload_if_needed<F: Fn(&mut Engines)>(&self, custom_callback: F) {
|
||||||
self.watcher.as_ref().map(|w| {
|
self.watcher.as_ref().map(|w| {
|
||||||
let rx_lock = w.lock().expect("receive queue lock");
|
let rx_lock = w.lock().expect("receive queue lock");
|
||||||
let mut changed = false;
|
let mut changed = false;
|
||||||
|
@ -117,7 +115,7 @@ pub struct TemplateFairing {
|
||||||
/// The user-provided customization callback, allowing the use of
|
/// The user-provided customization callback, allowing the use of
|
||||||
/// functionality specific to individual template engines. In debug mode,
|
/// functionality specific to individual template engines. In debug mode,
|
||||||
/// this callback might be run multiple times as templates are reloaded.
|
/// this callback might be run multiple times as templates are reloaded.
|
||||||
pub(crate) custom_callback: Box<Fn(&mut Engines) + Send + Sync + 'static>,
|
crate custom_callback: Box<Fn(&mut Engines) + Send + Sync + 'static>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Fairing for TemplateFairing {
|
impl Fairing for TemplateFairing {
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
extern crate handlebars;
|
use templates::serde::Serialize;
|
||||||
|
use templates::{Engine, TemplateInfo};
|
||||||
|
|
||||||
use super::serde::Serialize;
|
pub use templates::handlebars::Handlebars;
|
||||||
use super::{Engine, TemplateInfo};
|
|
||||||
|
|
||||||
pub use self::handlebars::Handlebars;
|
|
||||||
|
|
||||||
impl Engine for Handlebars {
|
impl Engine for Handlebars {
|
||||||
const EXT: &'static str = "hbs";
|
const EXT: &'static str = "hbs";
|
||||||
|
|
|
@ -2,43 +2,23 @@ use rocket::{Request, State, Outcome};
|
||||||
use rocket::http::Status;
|
use rocket::http::Status;
|
||||||
use rocket::request::{self, FromRequest};
|
use rocket::request::{self, FromRequest};
|
||||||
|
|
||||||
use super::ContextManager;
|
use templates::ContextManager;
|
||||||
|
|
||||||
/// Implements [`FromRequest`] for dynamiclly querying template metadata.
|
/// Request guard for dynamiclly querying template metadata.
|
||||||
///
|
///
|
||||||
/// # Usage
|
/// # Usage
|
||||||
///
|
///
|
||||||
/// First, ensure that the template [fairing](rocket::fairing),
|
/// The `Metadata` type implements Rocket's [`FromRequest`] trait, so it can be
|
||||||
/// [`Template::fairing()`](::Template::fairing()) is attached to your Rocket
|
/// used as a request guard in any request handler.
|
||||||
/// application:
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// # extern crate rocket;
|
|
||||||
/// # extern crate rocket_contrib;
|
|
||||||
/// #
|
|
||||||
/// use rocket_contrib::Template;
|
|
||||||
///
|
|
||||||
/// fn main() {
|
|
||||||
/// rocket::ignite()
|
|
||||||
/// .attach(Template::fairing())
|
|
||||||
/// // ...
|
|
||||||
/// # ;
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// The `TemplateMetadata` type implements Rocket's `FromRequest` trait, so it
|
|
||||||
/// can be used as a request guard in any request handler.
|
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # #![feature(proc_macro_hygiene, decl_macro)]
|
/// # #![feature(proc_macro_hygiene, decl_macro)]
|
||||||
/// # #[macro_use] extern crate rocket;
|
/// # #[macro_use] extern crate rocket;
|
||||||
/// # #[macro_use] extern crate rocket_contrib;
|
/// # #[macro_use] extern crate rocket_contrib;
|
||||||
/// # fn main() { }
|
/// use rocket_contrib::templates::{Template, Metadata};
|
||||||
/// #
|
|
||||||
/// use rocket_contrib::{Template, TemplateMetadata};
|
|
||||||
///
|
///
|
||||||
/// #[get("/")]
|
/// #[get("/")]
|
||||||
/// fn homepage(metadata: TemplateMetadata) -> Template {
|
/// fn homepage(metadata: Metadata) -> Template {
|
||||||
/// # use std::collections::HashMap;
|
/// # use std::collections::HashMap;
|
||||||
/// # let context: HashMap<String, String> = HashMap::new();
|
/// # let context: HashMap<String, String> = HashMap::new();
|
||||||
/// // Conditionally render a template if it's available.
|
/// // Conditionally render a template if it's available.
|
||||||
|
@ -48,19 +28,27 @@ use super::ContextManager;
|
||||||
/// Template::render("fallback", &context)
|
/// Template::render("fallback", &context)
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// fn main() {
|
||||||
|
/// rocket::ignite()
|
||||||
|
/// .attach(Template::fairing())
|
||||||
|
/// // ...
|
||||||
|
/// # ;
|
||||||
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub struct TemplateMetadata<'a>(&'a ContextManager);
|
pub struct Metadata<'a>(&'a ContextManager);
|
||||||
|
|
||||||
impl<'a> TemplateMetadata<'a> {
|
impl<'a> Metadata<'a> {
|
||||||
/// Returns `true` if the template with name `name` was loaded at start-up
|
/// Returns `true` if the template with name `name` was loaded at start-up
|
||||||
/// time. Otherwise, returns `false`.
|
/// time. Otherwise, returns `false`.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use rocket_contrib::TemplateMetadata;
|
/// use rocket_contrib::templates::Metadata;
|
||||||
///
|
///
|
||||||
/// fn handler(metadata: TemplateMetadata) {
|
/// fn handler(metadata: Metadata) {
|
||||||
/// // Returns `true` if the template with name `"name"` was loaded.
|
/// // Returns `true` if the template with name `"name"` was loaded.
|
||||||
/// let loaded = metadata.contains_template("name");
|
/// let loaded = metadata.contains_template("name");
|
||||||
/// }
|
/// }
|
||||||
|
@ -73,13 +61,13 @@ impl<'a> TemplateMetadata<'a> {
|
||||||
/// Retrieves the template metadata. If a template fairing hasn't been attached,
|
/// Retrieves the template metadata. If a template fairing hasn't been attached,
|
||||||
/// an error is printed and an empty `Err` with status `InternalServerError`
|
/// an error is printed and an empty `Err` with status `InternalServerError`
|
||||||
/// (`500`) is returned.
|
/// (`500`) is returned.
|
||||||
impl<'a, 'r> FromRequest<'a, 'r> for TemplateMetadata<'a> {
|
impl<'a, 'r> FromRequest<'a, 'r> for Metadata<'a> {
|
||||||
type Error = ();
|
type Error = ();
|
||||||
|
|
||||||
fn from_request(request: &'a Request) -> request::Outcome<Self, ()> {
|
fn from_request(request: &'a Request) -> request::Outcome<Self, ()> {
|
||||||
request.guard::<State<ContextManager>>()
|
request.guard::<State<ContextManager>>()
|
||||||
.succeeded()
|
.succeeded()
|
||||||
.and_then(|cm| Some(Outcome::Success(TemplateMetadata(cm.inner()))))
|
.and_then(|cm| Some(Outcome::Success(Metadata(cm.inner()))))
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
error_!("Uninitialized template context: missing fairing.");
|
error_!("Uninitialized template context: missing fairing.");
|
||||||
info_!("To use templates, you must attach `Template::fairing()`.");
|
info_!("To use templates, you must attach `Template::fairing()`.");
|
||||||
|
|
|
@ -2,7 +2,10 @@ extern crate serde;
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
extern crate glob;
|
extern crate glob;
|
||||||
|
|
||||||
|
#[cfg(feature = "tera_templates")] pub extern crate tera;
|
||||||
#[cfg(feature = "tera_templates")] mod tera_templates;
|
#[cfg(feature = "tera_templates")] mod tera_templates;
|
||||||
|
|
||||||
|
#[cfg(feature = "handlebars_templates")] pub extern crate handlebars;
|
||||||
#[cfg(feature = "handlebars_templates")] mod handlebars_templates;
|
#[cfg(feature = "handlebars_templates")] mod handlebars_templates;
|
||||||
|
|
||||||
mod engine;
|
mod engine;
|
||||||
|
@ -11,11 +14,12 @@ mod context;
|
||||||
mod metadata;
|
mod metadata;
|
||||||
|
|
||||||
pub use self::engine::Engines;
|
pub use self::engine::Engines;
|
||||||
pub use self::metadata::TemplateMetadata;
|
pub use self::metadata::Metadata;
|
||||||
|
crate use self::context::Context;
|
||||||
|
crate use self::fairing::ContextManager;
|
||||||
|
|
||||||
use self::engine::Engine;
|
use self::engine::Engine;
|
||||||
use self::fairing::{TemplateFairing, ContextManager};
|
use self::fairing::TemplateFairing;
|
||||||
use self::context::Context;
|
|
||||||
use self::serde::Serialize;
|
use self::serde::Serialize;
|
||||||
use self::serde_json::{Value, to_value};
|
use self::serde_json::{Value, to_value};
|
||||||
use self::glob::glob;
|
use self::glob::glob;
|
||||||
|
@ -99,14 +103,12 @@ const DEFAULT_TEMPLATE_DIR: &str = "templates";
|
||||||
/// application:
|
/// application:
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// extern crate rocket;
|
/// # extern crate rocket;
|
||||||
/// extern crate rocket_contrib;
|
/// # extern crate rocket_contrib;
|
||||||
///
|
/// use rocket_contrib::templates::Template;
|
||||||
/// use rocket_contrib::Template;
|
|
||||||
///
|
///
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
/// rocket::ignite()
|
/// rocket::ignite()
|
||||||
/// // ...
|
|
||||||
/// .attach(Template::fairing())
|
/// .attach(Template::fairing())
|
||||||
/// // ...
|
/// // ...
|
||||||
/// # ;
|
/// # ;
|
||||||
|
@ -116,10 +118,16 @@ const DEFAULT_TEMPLATE_DIR: &str = "templates";
|
||||||
/// The `Template` type implements Rocket's [`Responder`] trait, so it can be
|
/// The `Template` type implements Rocket's [`Responder`] trait, so it can be
|
||||||
/// returned from a request handler directly:
|
/// returned from a request handler directly:
|
||||||
///
|
///
|
||||||
/// ```rust,ignore
|
/// ```rust
|
||||||
|
/// # #![feature(proc_macro_hygiene, decl_macro)]
|
||||||
|
/// # #[macro_use] extern crate rocket;
|
||||||
|
/// # #[macro_use] extern crate rocket_contrib;
|
||||||
|
/// # fn context() { }
|
||||||
|
/// use rocket_contrib::templates::Template;
|
||||||
|
///
|
||||||
/// #[get("/")]
|
/// #[get("/")]
|
||||||
/// fn index() -> Template {
|
/// fn index() -> Template {
|
||||||
/// let context = ...;
|
/// let context = context();
|
||||||
/// Template::render("index", &context)
|
/// Template::render("index", &context)
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -136,7 +144,7 @@ pub struct Template {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TemplateInfo {
|
crate struct TemplateInfo {
|
||||||
/// The complete path, including `template_dir`, to this template.
|
/// The complete path, including `template_dir`, to this template.
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
/// The extension for the engine of this template.
|
/// The extension for the engine of this template.
|
||||||
|
@ -166,7 +174,7 @@ impl Template {
|
||||||
/// extern crate rocket;
|
/// extern crate rocket;
|
||||||
/// extern crate rocket_contrib;
|
/// extern crate rocket_contrib;
|
||||||
///
|
///
|
||||||
/// use rocket_contrib::Template;
|
/// use rocket_contrib::templates::Template;
|
||||||
///
|
///
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
/// rocket::ignite()
|
/// rocket::ignite()
|
||||||
|
@ -192,7 +200,7 @@ impl Template {
|
||||||
/// extern crate rocket;
|
/// extern crate rocket;
|
||||||
/// extern crate rocket_contrib;
|
/// extern crate rocket_contrib;
|
||||||
///
|
///
|
||||||
/// use rocket_contrib::Template;
|
/// use rocket_contrib::templates::Template;
|
||||||
///
|
///
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
/// rocket::ignite()
|
/// rocket::ignite()
|
||||||
|
@ -218,7 +226,7 @@ impl Template {
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use std::collections::HashMap;
|
/// use std::collections::HashMap;
|
||||||
/// use rocket_contrib::Template;
|
/// use rocket_contrib::templates::Template;
|
||||||
///
|
///
|
||||||
/// // Create a `context`. Here, just an empty `HashMap`.
|
/// // Create a `context`. Here, just an empty `HashMap`.
|
||||||
/// let mut context = HashMap::new();
|
/// let mut context = HashMap::new();
|
||||||
|
@ -235,9 +243,9 @@ impl Template {
|
||||||
|
|
||||||
/// Render the template named `name` with the context `context` into a
|
/// Render the template named `name` with the context `context` into a
|
||||||
/// `String`. This method should **not** be used in any running Rocket
|
/// `String`. This method should **not** be used in any running Rocket
|
||||||
/// application. This method should only be used during testing to
|
/// application. This method should only be used during testing to validate
|
||||||
/// validate `Template` responses. For other uses, use
|
/// `Template` responses. For other uses, use [`render()`](#method.render)
|
||||||
/// [`render`](#method.render) instead.
|
/// instead.
|
||||||
///
|
///
|
||||||
/// The `context` can be of any type that implements `Serialize`. This is
|
/// The `context` can be of any type that implements `Serialize`. This is
|
||||||
/// typically a `HashMap` or a custom `struct`.
|
/// typically a `HashMap` or a custom `struct`.
|
||||||
|
@ -253,7 +261,7 @@ impl Template {
|
||||||
/// # extern crate rocket_contrib;
|
/// # extern crate rocket_contrib;
|
||||||
/// use std::collections::HashMap;
|
/// use std::collections::HashMap;
|
||||||
///
|
///
|
||||||
/// use rocket_contrib::Template;
|
/// use rocket_contrib::templates::Template;
|
||||||
/// use rocket::local::Client;
|
/// use rocket::local::Client;
|
||||||
///
|
///
|
||||||
/// fn main() {
|
/// fn main() {
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
extern crate tera;
|
use templates::serde::Serialize;
|
||||||
|
use templates::{Engine, TemplateInfo};
|
||||||
|
|
||||||
use super::serde::Serialize;
|
pub use templates::tera::Tera;
|
||||||
use super::{Engine, TemplateInfo};
|
|
||||||
|
|
||||||
pub use self::tera::Tera;
|
|
||||||
|
|
||||||
impl Engine for Tera {
|
impl Engine for Tera {
|
||||||
const EXT: &'static str = "tera";
|
const EXT: &'static str = "tera";
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
extern crate uuid as uuid_ext;
|
pub extern crate uuid as uuid_crate;
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
@ -7,7 +7,7 @@ use std::ops::Deref;
|
||||||
use rocket::request::{FromParam, FromFormValue};
|
use rocket::request::{FromParam, FromFormValue};
|
||||||
use rocket::http::RawStr;
|
use rocket::http::RawStr;
|
||||||
|
|
||||||
pub use self::uuid_ext::parser::ParseError as UuidParseError;
|
pub use self::uuid_crate::parser::ParseError;
|
||||||
|
|
||||||
/// Implements [`FromParam`] and [`FromFormValue`] for accepting UUID values
|
/// Implements [`FromParam`] and [`FromFormValue`] for accepting UUID values
|
||||||
/// from the [`uuid`] crate.
|
/// from the [`uuid`] crate.
|
||||||
|
@ -26,7 +26,12 @@ pub use self::uuid_ext::parser::ParseError as UuidParseError;
|
||||||
///
|
///
|
||||||
/// You can use the `Uuid` type directly as a target of a dynamic parameter:
|
/// You can use the `Uuid` type directly as a target of a dynamic parameter:
|
||||||
///
|
///
|
||||||
/// ```rust,ignore
|
/// ```rust
|
||||||
|
/// # #![feature(proc_macro_hygiene, decl_macro)]
|
||||||
|
/// # #[macro_use] extern crate rocket;
|
||||||
|
/// # #[macro_use] extern crate rocket_contrib;
|
||||||
|
/// use rocket_contrib::uuid::Uuid;
|
||||||
|
///
|
||||||
/// #[get("/users/<id>")]
|
/// #[get("/users/<id>")]
|
||||||
/// fn user(id: Uuid) -> String {
|
/// fn user(id: Uuid) -> String {
|
||||||
/// format!("We found: {}", id)
|
/// format!("We found: {}", id)
|
||||||
|
@ -35,18 +40,18 @@ pub use self::uuid_ext::parser::ParseError as UuidParseError;
|
||||||
///
|
///
|
||||||
/// You can also use the `Uuid` as a form value, including in query strings:
|
/// You can also use the `Uuid` as a form value, including in query strings:
|
||||||
///
|
///
|
||||||
/// ```rust,ignore
|
/// ```rust
|
||||||
/// #[derive(FromForm)]
|
/// # #![feature(proc_macro_hygiene, decl_macro)]
|
||||||
/// struct UserQuery {
|
/// # #[macro_use] extern crate rocket;
|
||||||
/// id: Uuid
|
/// # #[macro_use] extern crate rocket_contrib;
|
||||||
/// }
|
/// use rocket_contrib::uuid::Uuid;
|
||||||
///
|
///
|
||||||
/// #[post("/user?<user_query>")]
|
/// #[get("/user?<id>")]
|
||||||
/// fn user(user_query: UserQuery) -> String {
|
/// fn user(id: Uuid) -> String {
|
||||||
/// format!("User ID: {}", user_query.id)
|
/// format!("User ID: {}", id)
|
||||||
/// }
|
/// }
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||||
pub struct Uuid(uuid_ext::Uuid);
|
pub struct Uuid(uuid_crate::Uuid);
|
||||||
|
|
||||||
impl Uuid {
|
impl Uuid {
|
||||||
/// Consumes the Uuid wrapper, returning the underlying `Uuid` type.
|
/// Consumes the Uuid wrapper, returning the underlying `Uuid` type.
|
||||||
|
@ -54,17 +59,21 @@ impl Uuid {
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// # extern crate rocket_contrib;
|
/// # extern crate rocket_contrib;
|
||||||
/// # extern crate uuid;
|
|
||||||
/// # use std::str::FromStr;
|
/// # use std::str::FromStr;
|
||||||
/// # fn main() {
|
/// # fn main() {
|
||||||
|
/// use rocket_contrib::uuid::{uuid_crate, Uuid};
|
||||||
|
///
|
||||||
/// let uuid_str = "c1aa1e3b-9614-4895-9ebd-705255fa5bc2";
|
/// let uuid_str = "c1aa1e3b-9614-4895-9ebd-705255fa5bc2";
|
||||||
/// let real_uuid = uuid::Uuid::from_str(uuid_str).unwrap();
|
/// let real_uuid = uuid_crate::Uuid::from_str(uuid_str).unwrap();
|
||||||
/// let my_inner_uuid = rocket_contrib::Uuid::from_str(uuid_str).unwrap().into_inner();
|
/// let my_inner_uuid = Uuid::from_str(uuid_str)
|
||||||
|
/// .expect("valid UUID string")
|
||||||
|
/// .into_inner();
|
||||||
|
///
|
||||||
/// assert_eq!(real_uuid, my_inner_uuid);
|
/// assert_eq!(real_uuid, my_inner_uuid);
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn into_inner(self) -> uuid_ext::Uuid {
|
pub fn into_inner(self) -> uuid_crate::Uuid {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,10 +86,10 @@ impl fmt::Display for Uuid {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FromParam<'a> for Uuid {
|
impl<'a> FromParam<'a> for Uuid {
|
||||||
type Error = UuidParseError;
|
type Error = ParseError;
|
||||||
|
|
||||||
/// A value is successfully parsed if `param` is a properly formatted Uuid.
|
/// A value is successfully parsed if `param` is a properly formatted Uuid.
|
||||||
/// Otherwise, a `UuidParseError` is returned.
|
/// Otherwise, a `ParseError` is returned.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from_param(param: &'a RawStr) -> Result<Uuid, Self::Error> {
|
fn from_param(param: &'a RawStr) -> Result<Uuid, Self::Error> {
|
||||||
param.parse()
|
param.parse()
|
||||||
|
@ -99,7 +108,7 @@ impl<'v> FromFormValue<'v> for Uuid {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for Uuid {
|
impl FromStr for Uuid {
|
||||||
type Err = UuidParseError;
|
type Err = ParseError;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_str(s: &str) -> Result<Uuid, Self::Err> {
|
fn from_str(s: &str) -> Result<Uuid, Self::Err> {
|
||||||
|
@ -108,23 +117,23 @@ impl FromStr for Uuid {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for Uuid {
|
impl Deref for Uuid {
|
||||||
type Target = uuid_ext::Uuid;
|
type Target = uuid_crate::Uuid;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq<uuid_ext::Uuid> for Uuid {
|
impl PartialEq<uuid_crate::Uuid> for Uuid {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn eq(&self, other: &uuid_ext::Uuid) -> bool {
|
fn eq(&self, other: &uuid_crate::Uuid) -> bool {
|
||||||
self.0.eq(other)
|
self.0.eq(other)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::uuid_ext;
|
use super::uuid_crate;
|
||||||
use super::Uuid;
|
use super::Uuid;
|
||||||
use super::FromParam;
|
use super::FromParam;
|
||||||
use super::FromStr;
|
use super::FromStr;
|
||||||
|
@ -147,8 +156,8 @@ mod test {
|
||||||
fn test_into_inner() {
|
fn test_into_inner() {
|
||||||
let uuid_str = "c1aa1e3b-9614-4895-9ebd-705255fa5bc2";
|
let uuid_str = "c1aa1e3b-9614-4895-9ebd-705255fa5bc2";
|
||||||
let uuid_wrapper = Uuid::from_param(uuid_str.into()).unwrap();
|
let uuid_wrapper = Uuid::from_param(uuid_str.into()).unwrap();
|
||||||
let real_uuid: uuid_ext::Uuid = uuid_str.parse().unwrap();
|
let real_uuid: uuid_crate::Uuid = uuid_str.parse().unwrap();
|
||||||
let inner_uuid: uuid_ext::Uuid = uuid_wrapper.into_inner();
|
let inner_uuid: uuid_crate::Uuid = uuid_wrapper.into_inner();
|
||||||
assert_eq!(real_uuid, inner_uuid)
|
assert_eq!(real_uuid, inner_uuid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +165,7 @@ mod test {
|
||||||
fn test_partial_eq() {
|
fn test_partial_eq() {
|
||||||
let uuid_str = "c1aa1e3b-9614-4895-9ebd-705255fa5bc2";
|
let uuid_str = "c1aa1e3b-9614-4895-9ebd-705255fa5bc2";
|
||||||
let uuid_wrapper = Uuid::from_param(uuid_str.into()).unwrap();
|
let uuid_wrapper = Uuid::from_param(uuid_str.into()).unwrap();
|
||||||
let real_uuid: uuid_ext::Uuid = uuid_str.parse().unwrap();
|
let real_uuid: uuid_crate::Uuid = uuid_str.parse().unwrap();
|
||||||
assert_eq!(uuid_wrapper, real_uuid)
|
assert_eq!(uuid_wrapper, real_uuid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
extern crate rocket_contrib;
|
extern crate rocket_contrib;
|
||||||
|
|
||||||
#[cfg(feature = "databases")]
|
#[cfg(all(feature = "diesel_sqlite_pool", feature = "diesel_postgres_pool"))]
|
||||||
mod databases_tests {
|
mod databases_tests {
|
||||||
use rocket_contrib::databases::{database, diesel};
|
use rocket_contrib::databases::{database, diesel};
|
||||||
|
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
extern crate rocket_contrib;
|
extern crate rocket_contrib;
|
||||||
|
|
||||||
#[cfg(feature = "static_files")]
|
#[cfg(feature = "static")]
|
||||||
mod static_files_tests {
|
mod static_tests {
|
||||||
use std::{io::Read, fs::File};
|
use std::{io::Read, fs::File};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use rocket::{self, Rocket};
|
use rocket::{self, Rocket};
|
||||||
use rocket_contrib::static_files::{StaticFiles, Options};
|
use rocket_contrib::serve::{StaticFiles, Options};
|
||||||
use rocket::http::Status;
|
use rocket::http::Status;
|
||||||
use rocket::local::Client;
|
use rocket::local::Client;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#![feature(proc_macro_hygiene, decl_macro)]
|
#![feature(proc_macro_hygiene, decl_macro)]
|
||||||
|
|
||||||
|
#[cfg(feature = "templates")]
|
||||||
#[macro_use] extern crate rocket;
|
#[macro_use] extern crate rocket;
|
||||||
|
|
||||||
|
#[cfg(feature = "templates")]
|
||||||
extern crate rocket_contrib;
|
extern crate rocket_contrib;
|
||||||
|
|
||||||
#[cfg(feature = "templates")]
|
#[cfg(feature = "templates")]
|
||||||
|
@ -9,10 +12,10 @@ mod templates_tests {
|
||||||
|
|
||||||
use rocket::{Rocket, http::RawStr};
|
use rocket::{Rocket, http::RawStr};
|
||||||
use rocket::config::{Config, Environment};
|
use rocket::config::{Config, Environment};
|
||||||
use rocket_contrib::{Template, TemplateMetadata};
|
use rocket_contrib::templates::{Template, Metadata};
|
||||||
|
|
||||||
#[get("/<engine>/<name>")]
|
#[get("/<engine>/<name>")]
|
||||||
fn template_check(md: TemplateMetadata, engine: &RawStr, name: &RawStr) -> Option<()> {
|
fn template_check(md: Metadata, engine: &RawStr, name: &RawStr) -> Option<()> {
|
||||||
match md.contains_template(&format!("{}/{}", engine, name)) {
|
match md.contains_template(&format!("{}/{}", engine, name)) {
|
||||||
true => Some(()),
|
true => Some(()),
|
||||||
false => None
|
false => None
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#![feature(proc_macro_hygiene, decl_macro)]
|
#![feature(proc_macro_hygiene, decl_macro)]
|
||||||
|
|
||||||
extern crate rocket_contrib;
|
|
||||||
#[macro_use] extern crate rocket;
|
#[macro_use] extern crate rocket;
|
||||||
|
extern crate rocket_contrib;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
@ -11,7 +11,7 @@ use std::collections::HashMap;
|
||||||
use rocket::request::Form;
|
use rocket::request::Form;
|
||||||
use rocket::response::Redirect;
|
use rocket::response::Redirect;
|
||||||
use rocket::http::{Cookie, Cookies};
|
use rocket::http::{Cookie, Cookies};
|
||||||
use rocket_contrib::Template;
|
use rocket_contrib::templates::Template;
|
||||||
|
|
||||||
#[derive(FromForm)]
|
#[derive(FromForm)]
|
||||||
struct Message {
|
struct Message {
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::collections::HashMap;
|
||||||
use super::rocket;
|
use super::rocket;
|
||||||
use rocket::local::Client;
|
use rocket::local::Client;
|
||||||
use rocket::http::*;
|
use rocket::http::*;
|
||||||
use rocket_contrib::Template;
|
use rocket_contrib::templates::Template;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_submit() {
|
fn test_submit() {
|
||||||
|
|
|
@ -8,7 +8,7 @@ extern crate rocket_contrib;
|
||||||
|
|
||||||
use rocket::Request;
|
use rocket::Request;
|
||||||
use rocket::response::Redirect;
|
use rocket::response::Redirect;
|
||||||
use rocket_contrib::{Template, handlebars};
|
use rocket_contrib::templates::{Template, handlebars};
|
||||||
|
|
||||||
use handlebars::{Helper, Handlebars, Context, RenderContext, Output, HelperResult, JsonRender};
|
use handlebars::{Helper, Handlebars, Context, RenderContext, Output, HelperResult, JsonRender};
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ use super::{rocket, TemplateContext};
|
||||||
use rocket::local::{Client, LocalResponse};
|
use rocket::local::{Client, LocalResponse};
|
||||||
use rocket::http::Method::*;
|
use rocket::http::Method::*;
|
||||||
use rocket::http::Status;
|
use rocket::http::Status;
|
||||||
use rocket_contrib::Template;
|
use rocket_contrib::templates::Template;
|
||||||
|
|
||||||
macro_rules! dispatch {
|
macro_rules! dispatch {
|
||||||
($method:expr, $path:expr, $test_fn:expr) => ({
|
($method:expr, $path:expr, $test_fn:expr) => ({
|
||||||
|
|
|
@ -6,10 +6,11 @@
|
||||||
|
|
||||||
#[cfg(test)] mod tests;
|
#[cfg(test)] mod tests;
|
||||||
|
|
||||||
use rocket::State;
|
|
||||||
use rocket_contrib::{Json, JsonValue};
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use rocket::State;
|
||||||
|
use rocket_contrib::json::{Json, JsonValue};
|
||||||
|
|
||||||
// The type to represent the ID of a message.
|
// The type to represent the ID of a message.
|
||||||
type ID = usize;
|
type ID = usize;
|
||||||
|
|
|
@ -6,7 +6,7 @@ extern crate rocket_contrib;
|
||||||
|
|
||||||
#[cfg(test)] mod tests;
|
#[cfg(test)] mod tests;
|
||||||
|
|
||||||
use rocket_contrib::MsgPack;
|
use rocket_contrib::msgpack::MsgPack;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct Message<'r> {
|
struct Message<'r> {
|
||||||
|
|
|
@ -11,7 +11,7 @@ use rocket::outcome::IntoOutcome;
|
||||||
use rocket::request::{self, Form, FlashMessage, FromRequest, Request};
|
use rocket::request::{self, Form, FlashMessage, FromRequest, Request};
|
||||||
use rocket::response::{Redirect, Flash};
|
use rocket::response::{Redirect, Flash};
|
||||||
use rocket::http::{Cookie, Cookies};
|
use rocket::http::{Cookie, Cookies};
|
||||||
use rocket_contrib::Template;
|
use rocket_contrib::templates::Template;
|
||||||
|
|
||||||
#[derive(FromForm)]
|
#[derive(FromForm)]
|
||||||
struct Login {
|
struct Login {
|
||||||
|
|
|
@ -3,7 +3,7 @@ extern crate rocket_contrib;
|
||||||
|
|
||||||
#[cfg(test)] mod tests;
|
#[cfg(test)] mod tests;
|
||||||
|
|
||||||
use rocket_contrib::static_files::StaticFiles;
|
use rocket_contrib::serve::StaticFiles;
|
||||||
|
|
||||||
fn rocket() -> rocket::Rocket {
|
fn rocket() -> rocket::Rocket {
|
||||||
rocket::ignite().mount("/", StaticFiles::from("static"))
|
rocket::ignite().mount("/", StaticFiles::from("static"))
|
||||||
|
|
|
@ -11,7 +11,7 @@ use std::collections::HashMap;
|
||||||
|
|
||||||
use rocket::Request;
|
use rocket::Request;
|
||||||
use rocket::response::Redirect;
|
use rocket::response::Redirect;
|
||||||
use rocket_contrib::Template;
|
use rocket_contrib::templates::Template;
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct TemplateContext {
|
struct TemplateContext {
|
||||||
|
|
|
@ -2,7 +2,7 @@ use super::rocket;
|
||||||
use rocket::local::{Client, LocalResponse};
|
use rocket::local::{Client, LocalResponse};
|
||||||
use rocket::http::Method::*;
|
use rocket::http::Method::*;
|
||||||
use rocket::http::Status;
|
use rocket::http::Status;
|
||||||
use rocket_contrib::Template;
|
use rocket_contrib::templates::Template;
|
||||||
|
|
||||||
macro_rules! dispatch {
|
macro_rules! dispatch {
|
||||||
($method:expr, $path:expr, $test_fn:expr) => ({
|
($method:expr, $path:expr, $test_fn:expr) => ({
|
||||||
|
|
|
@ -20,4 +20,4 @@ rand = "0.5"
|
||||||
[dependencies.rocket_contrib]
|
[dependencies.rocket_contrib]
|
||||||
path = "../../contrib/lib"
|
path = "../../contrib/lib"
|
||||||
default_features = false
|
default_features = false
|
||||||
features = ["tera_templates", "diesel_sqlite_pool", "static_files"]
|
features = ["tera_templates", "diesel_sqlite_pool", "serve"]
|
||||||
|
|
|
@ -14,7 +14,7 @@ use rocket::Rocket;
|
||||||
use rocket::fairing::AdHoc;
|
use rocket::fairing::AdHoc;
|
||||||
use rocket::request::{Form, FlashMessage};
|
use rocket::request::{Form, FlashMessage};
|
||||||
use rocket::response::{Flash, Redirect};
|
use rocket::response::{Flash, Redirect};
|
||||||
use rocket_contrib::{Template, databases::database, static_files::StaticFiles};
|
use rocket_contrib::{templates::Template, databases::database, serve::StaticFiles};
|
||||||
use diesel::SqliteConnection;
|
use diesel::SqliteConnection;
|
||||||
|
|
||||||
use task::{Task, Todo};
|
use task::{Task, Todo};
|
||||||
|
|
|
@ -2,18 +2,18 @@
|
||||||
|
|
||||||
#[macro_use] extern crate rocket;
|
#[macro_use] extern crate rocket;
|
||||||
#[macro_use] extern crate lazy_static;
|
#[macro_use] extern crate lazy_static;
|
||||||
extern crate uuid;
|
|
||||||
extern crate rocket_contrib;
|
extern crate rocket_contrib;
|
||||||
|
extern crate uuid;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use rocket_contrib::Uuid;
|
use rocket_contrib::uuid::Uuid;
|
||||||
|
|
||||||
#[cfg(test)] mod tests;
|
#[cfg(test)] mod tests;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
// A small people lookup table for the sake of this example. In a real
|
// A small people lookup table for the sake of this example. In a real
|
||||||
// application this could be a database lookup. Notice that we use the
|
// application this could be a database lookup. Notice that we use the
|
||||||
// uuid::Uuid type here and not the rocket_contrib::Uuid type.
|
// uuid::Uuid type here and not the rocket_contrib::uuid::Uuid type.
|
||||||
static ref PEOPLE: HashMap<uuid::Uuid, &'static str> = {
|
static ref PEOPLE: HashMap<uuid::Uuid, &'static str> = {
|
||||||
let mut m = HashMap::new();
|
let mut m = HashMap::new();
|
||||||
let lacy_id = uuid::Uuid::parse_str("7f205202-7ba1-4c39-b2fc-3e630722bf9f").unwrap();
|
let lacy_id = uuid::Uuid::parse_str("7f205202-7ba1-4c39-b2fc-3e630722bf9f").unwrap();
|
||||||
|
@ -29,7 +29,7 @@ lazy_static! {
|
||||||
#[get("/people/<id>")]
|
#[get("/people/<id>")]
|
||||||
fn people(id: Uuid) -> Result<String, String> {
|
fn people(id: Uuid) -> Result<String, String> {
|
||||||
// Because Uuid implements the Deref trait, we use Deref coercion to convert
|
// Because Uuid implements the Deref trait, we use Deref coercion to convert
|
||||||
// rocket_contrib::Uuid to uuid::Uuid.
|
// rocket_contrib::uuid::Uuid to uuid::Uuid.
|
||||||
Ok(PEOPLE.get(&id)
|
Ok(PEOPLE.get(&id)
|
||||||
.map(|person| format!("We found: {}", person))
|
.map(|person| format!("We found: {}", person))
|
||||||
.ok_or_else(|| format!("Person not found for UUID: {}", id))?)
|
.ok_or_else(|| format!("Person not found for UUID: {}", id))?)
|
||||||
|
|
|
@ -85,7 +85,7 @@ if [ "$1" = "--contrib" ]; then
|
||||||
msgpack
|
msgpack
|
||||||
tera_templates
|
tera_templates
|
||||||
handlebars_templates
|
handlebars_templates
|
||||||
static_files
|
serve
|
||||||
diesel_postgres_pool
|
diesel_postgres_pool
|
||||||
diesel_sqlite_pool
|
diesel_sqlite_pool
|
||||||
diesel_mysql_pool
|
diesel_mysql_pool
|
||||||
|
|
Loading…
Reference in New Issue