Document the config module.

This commit is contained in:
Sergio Benitez 2016-10-18 12:04:56 -07:00
parent 5a1a303c59
commit 2a0535e1f7
6 changed files with 198 additions and 6 deletions

3
.gitignore vendored
View File

@ -19,3 +19,6 @@ Cargo.lock
# Scratch list of items that need to get done. # Scratch list of items that need to get done.
_TODO _TODO
# The upload script, for now.
scripts/upload-docs.sh

View File

@ -128,7 +128,7 @@ lazy_static! {
}).unwrap_or(DEFAULT_TEMPLATE_DIR); }).unwrap_or(DEFAULT_TEMPLATE_DIR);
config.root().join(dir).to_string_lossy().into_owned() config.root().join(dir).to_string_lossy().into_owned()
}).unwrap_or("templates".to_string()) }).unwrap_or(DEFAULT_TEMPLATE_DIR.to_string())
}; };
} }

View File

@ -10,11 +10,16 @@ use config::{self, Environment, ConfigError};
use logger::LoggingLevel; use logger::LoggingLevel;
use toml::Value; use toml::Value;
/// The core configuration structure.
#[derive(PartialEq)] #[derive(PartialEq)]
pub struct Config { pub struct Config {
/// The address to serve on.
pub address: String, pub address: String,
/// The port to serve on.
pub port: usize, pub port: usize,
/// How much information to log.
pub log_level: LoggingLevel, pub log_level: LoggingLevel,
/// The environment that this configuration corresponds to.
pub env: Environment, pub env: Environment,
session_key: RefCell<Option<String>>, session_key: RefCell<Option<String>>,
extra: HashMap<String, Value>, extra: HashMap<String, Value>,

View File

@ -8,14 +8,25 @@ use self::Environment::*;
pub const CONFIG_ENV: &'static str = "ROCKET_ENV"; pub const CONFIG_ENV: &'static str = "ROCKET_ENV";
/// An enum corresponding to the valid configuration environments.
#[derive(Hash, PartialEq, Eq, Debug, Clone, Copy)] #[derive(Hash, PartialEq, Eq, Debug, Clone, Copy)]
pub enum Environment { pub enum Environment {
/// The development environment.
Development, Development,
/// The staging environment.
Staging, Staging,
/// The production environment.
Production, Production,
} }
impl Environment { 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<Environment, ConfigError> { pub fn active() -> Result<Environment, ConfigError> {
let env_str = env::var(CONFIG_ENV).unwrap_or(Development.to_string()); let env_str = env::var(CONFIG_ENV).unwrap_or(Development.to_string());
env_str.parse().map_err(|_| ConfigError::BadEnv(env_str)) env_str.parse().map_err(|_| ConfigError::BadEnv(env_str))
@ -29,6 +40,50 @@ impl Environment {
impl FromStr for Environment { impl FromStr for Environment {
type Err = (); 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::<Environment>();
/// assert_eq!(env.unwrap(), Environment::Development);
///
/// let env = "dev".parse::<Environment>();
/// assert_eq!(env.unwrap(), Environment::Development);
///
/// let env = "devel".parse::<Environment>();
/// assert_eq!(env.unwrap(), Environment::Development);
/// ```
///
/// Parsing a staging environment:
///
/// ```rust
/// use rocket::config::Environment;
///
/// let env = "staging".parse::<Environment>();
/// assert_eq!(env.unwrap(), Environment::Staging);
///
/// let env = "stage".parse::<Environment>();
/// assert_eq!(env.unwrap(), Environment::Staging);
/// ```
///
/// Parsing a production environment:
///
/// ```rust
/// use rocket::config::Environment;
///
/// let env = "production".parse::<Environment>();
/// assert_eq!(env.unwrap(), Environment::Production);
///
/// let env = "prod".parse::<Environment>();
/// assert_eq!(env.unwrap(), Environment::Production);
/// ```
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
let env = match s { let env = match s {
"dev" | "devel" | "development" => Development, "dev" | "devel" | "development" => Development,

View File

@ -3,6 +3,7 @@ use super::Environment;
use term_painter::Color::White; use term_painter::Color::White;
use term_painter::ToStyle; use term_painter::ToStyle;
/// The type of a configuration parsing error.
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct ParsingError { pub struct ParsingError {
pub byte_range: (usize, usize), pub byte_range: (usize, usize),
@ -11,24 +12,39 @@ pub struct ParsingError {
pub desc: String, pub desc: String,
} }
/// The type of a configuration error.
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub enum ConfigError { pub enum ConfigError {
/// The current working directory could not be determined.
BadCWD, BadCWD,
/// The configuration file was not found.
NotFound, NotFound,
/// There was an I/O error while reading the configuration file.
IOError, IOError,
/// (path, reason) /// The path at which the configuration file was found was invalid.
///
/// Parameters: (path, reason)
BadFilePath(String, &'static str), BadFilePath(String, &'static str),
/// (environment_name) /// An environment specified in `ROCKET_ENV` is invalid.
///
/// Parameters: (environment_name)
BadEnv(String), BadEnv(String),
/// (environment_name, filename) /// An environment specified as a table `[environment]` is invalid.
///
/// Parameters: (environment_name, filename)
BadEntry(String, String), 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), 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<ParsingError>), ParseError(String, String, Vec<ParsingError>),
} }
impl ConfigError { impl ConfigError {
/// Prints this configuration error with Rocket formatting.
pub fn pretty_print(&self) { pub fn pretty_print(&self) {
use self::ConfigError::*; 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 { pub fn is_not_found(&self) -> bool {
use self::ConfigError::*; use self::ConfigError::*;
match *self { match *self {

View File

@ -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 error;
mod environment; mod environment;
mod config; mod config;
@ -23,8 +127,11 @@ static mut CONFIG: Option<RocketConfig> = None;
const CONFIG_FILENAME: &'static str = "Rocket.toml"; const CONFIG_FILENAME: &'static str = "Rocket.toml";
/// Wraps `std::result` with the error type of
/// [ConfigError](enum.ConfigError.html).
pub type Result<T> = ::std::result::Result<T, ConfigError>; pub type Result<T> = ::std::result::Result<T, ConfigError>;
#[doc(hidden)]
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct RocketConfig { pub struct RocketConfig {
pub active_env: Environment, pub active_env: Environment,
@ -200,6 +307,10 @@ unsafe fn private_init() {
} }
/// Retrieve the active configuration, if there is one. /// 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> { pub fn active() -> Option<&'static Config> {
unsafe { CONFIG.as_ref().map(|c| c.active()) } unsafe { CONFIG.as_ref().map(|c| c.active()) }
} }