diff --git a/.gitignore b/.gitignore index c4dfc9b3..313b28ea 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,6 @@ Cargo.lock # Scratch list of items that need to get done. _TODO + +# The upload script, for now. +scripts/upload-docs.sh diff --git a/contrib/src/templates/mod.rs b/contrib/src/templates/mod.rs index a8b9e042..5cef0bbb 100644 --- a/contrib/src/templates/mod.rs +++ b/contrib/src/templates/mod.rs @@ -128,7 +128,7 @@ lazy_static! { }).unwrap_or(DEFAULT_TEMPLATE_DIR); config.root().join(dir).to_string_lossy().into_owned() - }).unwrap_or("templates".to_string()) + }).unwrap_or(DEFAULT_TEMPLATE_DIR.to_string()) }; } diff --git a/lib/src/config/config.rs b/lib/src/config/config.rs index f550a009..cbca1183 100644 --- a/lib/src/config/config.rs +++ b/lib/src/config/config.rs @@ -10,11 +10,16 @@ use config::{self, Environment, ConfigError}; use logger::LoggingLevel; use toml::Value; +/// The core configuration structure. #[derive(PartialEq)] pub struct Config { + /// The address to serve on. pub address: String, + /// The port to serve on. pub port: usize, + /// How much information to log. pub log_level: LoggingLevel, + /// The environment that this configuration corresponds to. pub env: Environment, session_key: RefCell>, extra: HashMap, diff --git a/lib/src/config/environment.rs b/lib/src/config/environment.rs index fff2ebae..01bc9b31 100644 --- a/lib/src/config/environment.rs +++ b/lib/src/config/environment.rs @@ -8,14 +8,25 @@ use self::Environment::*; pub const CONFIG_ENV: &'static str = "ROCKET_ENV"; +/// An enum corresponding to the valid configuration environments. #[derive(Hash, PartialEq, Eq, Debug, Clone, Copy)] pub enum Environment { + /// The development environment. Development, + /// The staging environment. Staging, + /// The production environment. Production, } impl Environment { + /// Retrieves the "active" environment as determined by the `ROCKET_ENV` + /// environment variable. Returns `Development` if `ROCKET_ENV` is not set. + /// + /// # Errors + /// + /// Returns a `BadEnv` `ConfigError` if `ROCKET_ENV` contains an invalid + /// environment name. pub fn active() -> Result { let env_str = env::var(CONFIG_ENV).unwrap_or(Development.to_string()); env_str.parse().map_err(|_| ConfigError::BadEnv(env_str)) @@ -29,6 +40,50 @@ impl Environment { impl FromStr for Environment { type Err = (); + + /// Parses a configuration environment from a string. Should be used + /// indirectly via `str`'s `parse` method. + /// + /// # Examples + /// + /// Parsing a development environment: + /// + /// ```rust + /// use rocket::config::Environment; + /// + /// let env = "development".parse::(); + /// assert_eq!(env.unwrap(), Environment::Development); + /// + /// let env = "dev".parse::(); + /// assert_eq!(env.unwrap(), Environment::Development); + /// + /// let env = "devel".parse::(); + /// assert_eq!(env.unwrap(), Environment::Development); + /// ``` + /// + /// Parsing a staging environment: + /// + /// ```rust + /// use rocket::config::Environment; + /// + /// let env = "staging".parse::(); + /// assert_eq!(env.unwrap(), Environment::Staging); + /// + /// let env = "stage".parse::(); + /// assert_eq!(env.unwrap(), Environment::Staging); + /// ``` + /// + /// Parsing a production environment: + /// + /// ```rust + /// use rocket::config::Environment; + /// + /// let env = "production".parse::(); + /// assert_eq!(env.unwrap(), Environment::Production); + /// + /// let env = "prod".parse::(); + /// assert_eq!(env.unwrap(), Environment::Production); + /// ``` fn from_str(s: &str) -> Result { let env = match s { "dev" | "devel" | "development" => Development, diff --git a/lib/src/config/error.rs b/lib/src/config/error.rs index 9882bc8d..7c43085f 100644 --- a/lib/src/config/error.rs +++ b/lib/src/config/error.rs @@ -3,6 +3,7 @@ use super::Environment; use term_painter::Color::White; use term_painter::ToStyle; +/// The type of a configuration parsing error. #[derive(Debug, PartialEq, Clone)] pub struct ParsingError { pub byte_range: (usize, usize), @@ -11,24 +12,39 @@ pub struct ParsingError { pub desc: String, } +/// The type of a configuration error. #[derive(Debug, PartialEq, Clone)] pub enum ConfigError { + /// The current working directory could not be determined. BadCWD, + /// The configuration file was not found. NotFound, + /// There was an I/O error while reading the configuration file. IOError, - /// (path, reason) + /// The path at which the configuration file was found was invalid. + /// + /// Parameters: (path, reason) BadFilePath(String, &'static str), - /// (environment_name) + /// An environment specified in `ROCKET_ENV` is invalid. + /// + /// Parameters: (environment_name) BadEnv(String), - /// (environment_name, filename) + /// An environment specified as a table `[environment]` is invalid. + /// + /// Parameters: (environment_name, filename) BadEntry(String, String), - /// (entry_name, expected_type, actual_type, filename) + /// A key was specified with a value of the wrong type. + /// + /// Parameters: (entry_name, expected_type, actual_type, filename) BadType(String, &'static str, &'static str, String), - /// (toml_source_string, filename, error_list) + /// There was a TOML parsing error. + /// + /// Parameters: (toml_source_string, filename, error_list) ParseError(String, String, Vec), } impl ConfigError { + /// Prints this configuration error with Rocket formatting. pub fn pretty_print(&self) { use self::ConfigError::*; @@ -70,6 +86,8 @@ impl ConfigError { } } + /// Whether this error is of `NotFound` variant. + #[inline(always)] pub fn is_not_found(&self) -> bool { use self::ConfigError::*; match *self { diff --git a/lib/src/config/mod.rs b/lib/src/config/mod.rs index f3d0acd2..fd06545e 100644 --- a/lib/src/config/mod.rs +++ b/lib/src/config/mod.rs @@ -1,3 +1,107 @@ +//! Application configuration and configuration parameter retrieval. +//! +//! This module implements configuration handling for Rocket. It implements +//! the parsing and interpretation of the `Rocket.toml` config file. It also +//! allows libraries to access values that have been configured by the user. +//! +//! ## Application Configuration +//! +//! ### Environments +//! +//! Rocket applications are always running in one of three environments: +//! +//! * development _or_ dev +//! * staging _or_ stage +//! * production _or_ prod +//! +//! Each environment can contain different configuration parameters. By default, +//! Rocket applications run in the **development** environment. The environment +//! can be changed via the `ROCKET_ENV` environment variable. For example, to +//! start a Rocket application in the **production** environment: +//! +//! ```sh +//! ROCKET_ENV=production ./target/release/rocket_app +//! ``` +//! +//! ### Configuration Parameters +//! +//! Each environments consists of several standard configuration parameters as +//! well as an arbitrary number of _extra_ configuration parameters, which are +//! not used by Rocket itself but can be used by external libraries. The +//! standard configuration parameters are: +//! +//! * **address**: _[string]_ an IP address or host the application will +//! listen on +//! * examples: `"localhost"`, `"0.0.0.0"`, `"1.2.3.4"` +//! * **port**: _[integer]_ a port number to listen on +//! * examples: `"8000"`, `"80"`, `"4242"` +//! * **log**: _[string]_ how much information to log; one of `"normal"`, +//! `"debug"`, or `"critical"` +//! * **session_key**: _[string]_ a 192-bit base64 encoded string (32 +//! characters) to use as the session key +//! * example: `"VheMwXIBygSmOlZAhuWl2B+zgvTN3WW5"` +//! +//! ### Rocket.toml +//! +//! The `Rocket.toml` file is used to specify the configuration parameters for +//! each environment. The file is optional. If it is not present, the default +//! configuration parameters are used. +//! +//! The file must be a series of tables, one for each environment, where each +//! table contains key-value pairs corresponding to configuration parameters for +//! that environment. If a configuration parameter is missing, the default value +//! is used. The following is a complete `Rocket.toml` file, where every +//! standard configuration parameter is specified with the default value: +//! +//! ```toml +//! [development] +//! address = "localhost" +//! port = 8000 +//! log = "normal" +//! +//! [staging] +//! address = "0.0.0.0" +//! port = 80 +//! log = "normal" +//! # don't use this key! generate your own and keep it private! +//! session_key = "VheMwXIBygSmOlZAhuWl2B+zgvTN3WW5" +//! +//! [production] +//! address = "0.0.0.0" +//! port = 80 +//! log = "critical" +//! # don't use this key! generate your own and keep it private! +//! session_key = "adL5fFIPmZBrlyHk2YT4NLV3YCk2gFXz" +//! ``` +//! +//! ## Retrieving Configuration Parameters +//! +//! Configuration parameters for the currently active configuration environment +//! can be retrieved via the [active](fn.active.html) function and methods on +//! the [Config](struct.Config.html) structure. The general structure is to call +//! `active` and then one of the `get_` methods on the returned `Config` +//! structure. +//! +//! As an example, consider the following code used by the `Template` type to +//! retrieve the value of the `template_dir` configuration parameter. If the +//! value isn't present or isn't a string, a default value is used. +//! +//! ```rust +//! use rocket::config; +//! +//! const DEFAULT_TEMPLATE_DIR: &'static str = "templates"; +//! +//! let template_dir = config::active().map(|config| { +//! let dir = config.get_str("template_dir") +//! .map_err(|e| if !e.is_not_found() { e.pretty_print(); }) +//! .unwrap_or(DEFAULT_TEMPLATE_DIR); +//! +//! config.root().join(dir).to_string_lossy().into_owned() +//! }).unwrap_or(DEFAULT_TEMPLATE_DIR.to_string()); +//! ``` +//! +//! Libraries should always use a default if a parameter is not defined. + mod error; mod environment; mod config; @@ -23,8 +127,11 @@ static mut CONFIG: Option = None; const CONFIG_FILENAME: &'static str = "Rocket.toml"; +/// Wraps `std::result` with the error type of +/// [ConfigError](enum.ConfigError.html). pub type Result = ::std::result::Result; +#[doc(hidden)] #[derive(Debug, PartialEq)] pub struct RocketConfig { pub active_env: Environment, @@ -200,6 +307,10 @@ unsafe fn private_init() { } /// Retrieve the active configuration, if there is one. +/// +/// This function is guaranteed to return `Some` once a Rocket application has +/// started. Before a Rocket application has started, or when there is no active +/// Rocket application (such as during testing), this function will return None. pub fn active() -> Option<&'static Config> { unsafe { CONFIG.as_ref().map(|c| c.active()) } }