mirror of https://github.com/rwf2/Rocket.git
Add 'Config::read()' and 'Config::read_from()'.
The former method allows constructing a 'Config' in the exact manner Rocket does internally: reading the active environment's properties from 'Rocket.toml' and overriding values from environment variables. The 'read_from()' property does the same except it allows a custom config file path. This PR also improves the internal structure of the configuration code.
This commit is contained in:
parent
ea9865ec42
commit
a4301c0a9a
|
@ -6,7 +6,7 @@ use std::fmt;
|
||||||
|
|
||||||
use crate::config::Environment::*;
|
use crate::config::Environment::*;
|
||||||
use crate::config::{Result, ConfigBuilder, Environment, ConfigError, LoggingLevel};
|
use crate::config::{Result, ConfigBuilder, Environment, ConfigError, LoggingLevel};
|
||||||
use crate::config::{Table, Value, Array, Datetime};
|
use crate::config::{FullConfig, Table, Value, Array, Datetime};
|
||||||
use crate::http::private::Key;
|
use crate::http::private::Key;
|
||||||
|
|
||||||
use super::custom_values::*;
|
use super::custom_values::*;
|
||||||
|
@ -75,8 +75,60 @@ macro_rules! config_from_raw {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
|
/// Reads configuration values from the nearest `Rocket.toml`, searching for
|
||||||
|
/// a file by that name upwards from the current working directory to its
|
||||||
|
/// parents, as well as from environment variables named `ROCKET_{PARAM}` as
|
||||||
|
/// specified in the [`config`](crate::config) module documentation. Returns
|
||||||
|
/// the active configuration.
|
||||||
|
///
|
||||||
|
/// Specifically, this method:
|
||||||
|
///
|
||||||
|
/// 1. Locates the nearest `Rocket.toml` configuration file.
|
||||||
|
/// 2. Retrieves the active environment according to
|
||||||
|
/// [`Environment::active()`].
|
||||||
|
/// 3. Parses and validates the configuration file in its entirety,
|
||||||
|
/// extracting the values from the active environment.
|
||||||
|
/// 4. Overrides parameters with values set in `ROCKET_{PARAM}`
|
||||||
|
/// environment variables.
|
||||||
|
///
|
||||||
|
/// Any error encountered while performing these steps is returned.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use rocket::config::Config;
|
||||||
|
///
|
||||||
|
/// # if false {
|
||||||
|
/// let config = Config::read().unwrap();
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
pub fn read() -> Result<Config> {
|
||||||
|
Self::read_from(&FullConfig::find()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This method is exactly like [`Config::read()`] except it uses the file
|
||||||
|
/// at `path` as the configuration file instead of searching for the nearest
|
||||||
|
/// `Rocket.toml`. The file must have the same format as `Rocket.toml`.
|
||||||
|
///
|
||||||
|
/// See [`Config::read()`] for more.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use rocket::config::Config;
|
||||||
|
///
|
||||||
|
/// # if false {
|
||||||
|
/// let config = Config::read_from("/var/my-config.toml").unwrap();
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
pub fn read_from<P: AsRef<Path>>(path: P) -> Result<Config> {
|
||||||
|
FullConfig::read_from(path.as_ref()).map(FullConfig::take_active)
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a builder for `Config` structure where the default parameters
|
/// Returns a builder for `Config` structure where the default parameters
|
||||||
/// are set to those of `env`.
|
/// are set to those of `env`. This _does not_ read any configuration
|
||||||
|
/// parameters from any source. See [`config`](crate::config) for a list of
|
||||||
|
/// defaults.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
|
@ -95,7 +147,12 @@ impl Config {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a `Config` with the default parameters for the environment
|
/// Returns a `Config` with the default parameters for the environment
|
||||||
/// `env`. See [`config`](crate::config) for a list of defaults.
|
/// `env`. This _does not_ read any configuration parameters from any
|
||||||
|
/// source. See [`config`](crate::config) for a list of defaults.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if randomness cannot be retrieved from the OS.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
|
@ -106,11 +163,12 @@ impl Config {
|
||||||
/// my_config.set_port(1001);
|
/// my_config.set_port(1001);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn new(env: Environment) -> Config {
|
pub fn new(env: Environment) -> Config {
|
||||||
Config::default(env)
|
Config::default(env).expect("failed to read randomness from the OS")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a `Config` with the default parameters of the active environment
|
/// Returns a `Config` with the default parameters of the active environment
|
||||||
/// as determined by the `ROCKET_ENV` environment variable.
|
/// as determined by the `ROCKET_ENV` environment variable. This _does not_
|
||||||
|
/// read any configuration parameters from any source.
|
||||||
///
|
///
|
||||||
/// If `ROCKET_ENV` is not set, the returned `Config` uses development
|
/// If `ROCKET_ENV` is not set, the returned `Config` uses development
|
||||||
/// environment parameters when the application was compiled in `debug` mode
|
/// environment parameters when the application was compiled in `debug` mode
|
||||||
|
@ -182,19 +240,17 @@ impl Config {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the default configuration for the environment `env` given that
|
/// Returns the default configuration for the environment `env` given that
|
||||||
/// the configuration was stored at `config_file_path`.
|
/// the configuration was stored at `path`. This doesn't read the file at
|
||||||
|
/// `path`; it simply uses `path` to set the config path property in the
|
||||||
|
/// returned `Config`.
|
||||||
///
|
///
|
||||||
/// # Error
|
/// # Error
|
||||||
///
|
///
|
||||||
/// Return a `BadFilePath` error if `path` does not have a parent.
|
/// Return a `BadFilePath` error if `path` does not have a parent.
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// Panics if randomness cannot be retrieved from the OS.
|
|
||||||
pub(crate) fn default_from<P>(env: Environment, path: P) -> Result<Config>
|
pub(crate) fn default_from<P>(env: Environment, path: P) -> Result<Config>
|
||||||
where P: AsRef<Path>
|
where P: AsRef<Path>
|
||||||
{
|
{
|
||||||
let mut config = Config::default(env);
|
let mut config = Config::default(env)?;
|
||||||
|
|
||||||
let config_file_path = path.as_ref().to_path_buf();
|
let config_file_path = path.as_ref().to_path_buf();
|
||||||
if let Some(parent) = config_file_path.parent() {
|
if let Some(parent) = config_file_path.parent() {
|
||||||
|
@ -209,18 +265,15 @@ impl Config {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the default configuration for the environment `env`.
|
/// Returns the default configuration for the environment `env`.
|
||||||
///
|
pub(crate) fn default(env: Environment) -> Result<Config> {
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// Panics if randomness cannot be retrieved from the OS.
|
|
||||||
pub(crate) fn default(env: Environment) -> Config {
|
|
||||||
// Note: This may truncate if num_cpus::get() / 2 > u16::max. That's okay.
|
// Note: This may truncate if num_cpus::get() / 2 > u16::max. That's okay.
|
||||||
let default_workers = (num_cpus::get() * 2) as u16;
|
let default_workers = (num_cpus::get() * 2) as u16;
|
||||||
|
|
||||||
// Use a generated secret key by default.
|
// Use a generated secret key by default.
|
||||||
let key = SecretKey::Generated(Key::generate());
|
let new_key = Key::try_generate().ok_or(ConfigError::RandFailure)?;
|
||||||
|
let key = SecretKey::Generated(new_key);
|
||||||
|
|
||||||
match env {
|
Ok(match env {
|
||||||
Development => {
|
Development => {
|
||||||
Config {
|
Config {
|
||||||
environment: Development,
|
environment: Development,
|
||||||
|
@ -269,7 +322,7 @@ impl Config {
|
||||||
root_path: None,
|
root_path: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a `BadType` error given the entry `name`, the invalid `val`
|
/// Constructs a `BadType` error given the entry `name`, the invalid `val`
|
||||||
|
|
|
@ -14,6 +14,8 @@ pub enum ConfigError {
|
||||||
NotFound,
|
NotFound,
|
||||||
/// There was an I/O error while reading the configuration file.
|
/// There was an I/O error while reading the configuration file.
|
||||||
IoError,
|
IoError,
|
||||||
|
/// There was an error retrieving randomness from the OS.
|
||||||
|
RandFailure,
|
||||||
/// There was an I/O error while setting a configuration parameter.
|
/// There was an I/O error while setting a configuration parameter.
|
||||||
///
|
///
|
||||||
/// Parameters: (io_error, config_param_name)
|
/// Parameters: (io_error, config_param_name)
|
||||||
|
@ -59,6 +61,7 @@ impl ConfigError {
|
||||||
match *self {
|
match *self {
|
||||||
NotFound => error!("config file was not found"),
|
NotFound => error!("config file was not found"),
|
||||||
IoError => error!("failed reading the config file: IO error"),
|
IoError => error!("failed reading the config file: IO error"),
|
||||||
|
RandFailure => error!("failed to read randomness from the OS"),
|
||||||
Io(ref error, param) => {
|
Io(ref error, param) => {
|
||||||
error!("I/O error while setting {}:", Paint::default(param).bold());
|
error!("I/O error while setting {}:", Paint::default(param).bold());
|
||||||
info_!("{}", error);
|
info_!("{}", error);
|
||||||
|
@ -135,6 +138,7 @@ impl fmt::Display for ConfigError {
|
||||||
match *self {
|
match *self {
|
||||||
NotFound => write!(f, "config file was not found"),
|
NotFound => write!(f, "config file was not found"),
|
||||||
IoError => write!(f, "I/O error while reading the config file"),
|
IoError => write!(f, "I/O error while reading the config file"),
|
||||||
|
RandFailure => write!(f, "randomness could not be retrieved from the OS"),
|
||||||
Io(ref e, p) => write!(f, "I/O error while setting '{}': {}", p, e),
|
Io(ref e, p) => write!(f, "I/O error while setting '{}': {}", p, e),
|
||||||
BadFilePath(ref p, _) => write!(f, "{:?} is not a valid config path", p),
|
BadFilePath(ref p, _) => write!(f, "{:?} is not a valid config path", p),
|
||||||
BadEnv(ref e) => write!(f, "{:?} is not a valid `ROCKET_ENV` value", e),
|
BadEnv(ref e) => write!(f, "{:?} is not a valid `ROCKET_ENV` value", e),
|
||||||
|
@ -159,6 +163,7 @@ impl Error for ConfigError {
|
||||||
match *self {
|
match *self {
|
||||||
NotFound => "config file was not found",
|
NotFound => "config file was not found",
|
||||||
IoError => "there was an I/O error while reading the config file",
|
IoError => "there was an I/O error while reading the config file",
|
||||||
|
RandFailure => "randomness could not be retrieved from the OS",
|
||||||
Io(..) => "an I/O error occured while setting a configuration parameter",
|
Io(..) => "an I/O error occured while setting a configuration parameter",
|
||||||
BadFilePath(..) => "the config file path is invalid",
|
BadFilePath(..) => "the config file path is invalid",
|
||||||
BadEntry(..) => "an environment specified as `[environment]` is invalid",
|
BadEntry(..) => "an environment specified as `[environment]` is invalid",
|
||||||
|
@ -177,6 +182,7 @@ impl PartialEq for ConfigError {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(&NotFound, &NotFound) => true,
|
(&NotFound, &NotFound) => true,
|
||||||
(&IoError, &IoError) => true,
|
(&IoError, &IoError) => true,
|
||||||
|
(&RandFailure, &RandFailure) => true,
|
||||||
(&Io(_, p1), &Io(_, p2)) => p1 == p2,
|
(&Io(_, p1), &Io(_, p2)) => p1 == p2,
|
||||||
(&BadFilePath(ref p1, _), &BadFilePath(ref p2, _)) => p1 == p2,
|
(&BadFilePath(ref p1, _), &BadFilePath(ref p2, _)) => p1 == p2,
|
||||||
(&BadEnv(ref e1), &BadEnv(ref e2)) => e1 == e2,
|
(&BadEnv(ref e1), &BadEnv(ref e2)) => e1 == e2,
|
||||||
|
@ -190,7 +196,7 @@ impl PartialEq for ConfigError {
|
||||||
k1 == k2 && v1 == v2
|
k1 == k2 && v1 == v2
|
||||||
}
|
}
|
||||||
(&Missing(ref k1), &Missing(ref k2)) => k1 == k2,
|
(&Missing(ref k1), &Missing(ref k2)) => k1 == k2,
|
||||||
(&NotFound, _) | (&IoError, _) | (&Io(..), _)
|
(&NotFound, _) | (&IoError, _) | (&RandFailure, _) | (&Io(..), _)
|
||||||
| (&BadFilePath(..), _) | (&BadEnv(..), _) | (&ParseError(..), _)
|
| (&BadFilePath(..), _) | (&BadEnv(..), _) | (&ParseError(..), _)
|
||||||
| (&UnknownKey(..), _) | (&BadEntry(..), _) | (&BadType(..), _)
|
| (&UnknownKey(..), _) | (&BadEntry(..), _) | (&BadType(..), _)
|
||||||
| (&BadEnvVal(..), _) | (&Missing(..), _) => false
|
| (&BadEnvVal(..), _) | (&Missing(..), _) => false
|
||||||
|
|
|
@ -192,7 +192,6 @@ use std::fs::{self, File};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process;
|
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
use toml;
|
use toml;
|
||||||
|
@ -206,7 +205,6 @@ pub use self::builder::ConfigBuilder;
|
||||||
pub use crate::logger::LoggingLevel;
|
pub use crate::logger::LoggingLevel;
|
||||||
pub(crate) use self::toml_ext::LoggedValue;
|
pub(crate) use self::toml_ext::LoggedValue;
|
||||||
|
|
||||||
use crate::logger;
|
|
||||||
use self::Environment::*;
|
use self::Environment::*;
|
||||||
use self::environment::CONFIG_ENV;
|
use self::environment::CONFIG_ENV;
|
||||||
use crate::logger::COLORS_ENV;
|
use crate::logger::COLORS_ENV;
|
||||||
|
@ -216,64 +214,60 @@ use crate::http::uncased::uncased_eq;
|
||||||
const CONFIG_FILENAME: &str = "Rocket.toml";
|
const CONFIG_FILENAME: &str = "Rocket.toml";
|
||||||
const GLOBAL_ENV_NAME: &str = "global";
|
const GLOBAL_ENV_NAME: &str = "global";
|
||||||
const ENV_VAR_PREFIX: &str = "ROCKET_";
|
const ENV_VAR_PREFIX: &str = "ROCKET_";
|
||||||
const PREHANDLED_VARS: [&str; 3] = ["ROCKET_CODEGEN_DEBUG", CONFIG_ENV, COLORS_ENV];
|
|
||||||
|
const CODEGEN_DEBUG_ENV: &str = "ROCKET_CODEGEN_DEBUG";
|
||||||
|
const PREHANDLED_VARS: [&str; 3] = [CODEGEN_DEBUG_ENV, CONFIG_ENV, COLORS_ENV];
|
||||||
|
|
||||||
/// Wraps `std::result` with the error type of [`ConfigError`].
|
/// Wraps `std::result` with the error type of [`ConfigError`].
|
||||||
pub type Result<T> = std::result::Result<T, ConfigError>;
|
pub type Result<T> = std::result::Result<T, ConfigError>;
|
||||||
|
|
||||||
#[doc(hidden)]
|
/// Stores a "full" config, which is all `Config`s for every environment.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct RocketConfig {
|
pub(crate) struct FullConfig {
|
||||||
pub active_env: Environment,
|
pub active_env: Environment,
|
||||||
config: HashMap<Environment, Config>,
|
config: HashMap<Environment, Config>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RocketConfig {
|
impl FullConfig {
|
||||||
/// Read the configuration from the `Rocket.toml` file. The file is search
|
/// Read the configuration from the `Rocket.toml` file. The file is searched
|
||||||
/// for recursively up the tree, starting from the CWD.
|
/// for recursively up the tree, starting from the CWD.
|
||||||
pub fn read() -> Result<RocketConfig> {
|
pub fn read_from(path: &Path) -> Result<FullConfig> {
|
||||||
// Find the config file, starting from the `cwd` and working backwards.
|
|
||||||
let file = RocketConfig::find()?;
|
|
||||||
|
|
||||||
// Try to open the config file for reading.
|
// Try to open the config file for reading.
|
||||||
let mut handle = File::open(&file).map_err(|_| ConfigError::IoError)?;
|
let mut handle = File::open(path).map_err(|_| ConfigError::IoError)?;
|
||||||
|
|
||||||
// Read the configure file to a string for parsing.
|
// Read the configure file to a string for parsing.
|
||||||
let mut contents = String::new();
|
let mut contents = String::new();
|
||||||
handle.read_to_string(&mut contents).map_err(|_| ConfigError::IoError)?;
|
handle.read_to_string(&mut contents).map_err(|_| ConfigError::IoError)?;
|
||||||
|
|
||||||
// Parse the config and return the result.
|
// Parse the config and return the result.
|
||||||
RocketConfig::parse(contents, &file)
|
let mut config = FullConfig::parse(contents, path)?;
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the default configuration for all environments and marks the
|
// Override any config values with those from the environment.
|
||||||
/// active environment (via the CONFIG_ENV variable) as active.
|
|
||||||
pub fn active_default_from(filename: Option<&Path>) -> Result<RocketConfig> {
|
|
||||||
let mut defaults = HashMap::new();
|
|
||||||
if let Some(path) = filename {
|
|
||||||
defaults.insert(Development, Config::default_from(Development, &path)?);
|
|
||||||
defaults.insert(Staging, Config::default_from(Staging, &path)?);
|
|
||||||
defaults.insert(Production, Config::default_from(Production, &path)?);
|
|
||||||
} else {
|
|
||||||
defaults.insert(Development, Config::default(Development));
|
|
||||||
defaults.insert(Staging, Config::default(Staging));
|
|
||||||
defaults.insert(Production, Config::default(Production));
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut config = RocketConfig {
|
|
||||||
active_env: Environment::active()?,
|
|
||||||
config: defaults,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Override any variables from the environment.
|
|
||||||
config.override_from_env()?;
|
config.override_from_env()?;
|
||||||
|
|
||||||
Ok(config)
|
Ok(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the default configuration for all environments and marks the
|
/// Return the default configuration for all environments and marks the
|
||||||
/// active environment (via the CONFIG_ENV variable) as active.
|
/// active environment (from `CONFIG_ENV`) as active. This doesn't read
|
||||||
pub fn active_default() -> Result<RocketConfig> {
|
/// `filename`, nor any other config values from any source; it simply uses
|
||||||
RocketConfig::active_default_from(None)
|
/// `filename` to set up the config path property in the returned `Config`.
|
||||||
|
pub fn active_default<'a, P: Into<Option<&'a Path>>>(filename: P) -> Result<FullConfig> {
|
||||||
|
let mut defaults = HashMap::new();
|
||||||
|
if let Some(path) = filename.into() {
|
||||||
|
defaults.insert(Development, Config::default_from(Development, &path)?);
|
||||||
|
defaults.insert(Staging, Config::default_from(Staging, &path)?);
|
||||||
|
defaults.insert(Production, Config::default_from(Production, &path)?);
|
||||||
|
} else {
|
||||||
|
defaults.insert(Development, Config::default(Development)?);
|
||||||
|
defaults.insert(Staging, Config::default(Staging)?);
|
||||||
|
defaults.insert(Production, Config::default(Production)?);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(FullConfig {
|
||||||
|
active_env: Environment::active()?,
|
||||||
|
config: defaults,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iteratively search for `CONFIG_FILENAME` starting at the current working
|
/// Iteratively search for `CONFIG_FILENAME` starting at the current working
|
||||||
|
@ -320,6 +314,7 @@ impl RocketConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves the `Config` for the environment `env`.
|
/// Retrieves the `Config` for the environment `env`.
|
||||||
|
#[cfg(test)]
|
||||||
pub fn get(&self, env: Environment) -> &Config {
|
pub fn get(&self, env: Environment) -> &Config {
|
||||||
match self.config.get(&env) {
|
match self.config.get(&env) {
|
||||||
Some(config) => config,
|
Some(config) => config,
|
||||||
|
@ -328,11 +323,16 @@ impl RocketConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves the `Config` for the active environment.
|
/// Retrieves the `Config` for the active environment.
|
||||||
#[inline]
|
#[cfg(test)]
|
||||||
pub fn active(&self) -> &Config {
|
pub fn active(&self) -> &Config {
|
||||||
self.get(self.active_env)
|
self.get(self.active_env)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retrieves the `Config` for the active environment.
|
||||||
|
pub fn take_active(mut self) -> Config {
|
||||||
|
self.config.remove(&self.active_env).expect("missing active config")
|
||||||
|
}
|
||||||
|
|
||||||
// Override all environments with values from env variables if present.
|
// Override all environments with values from env variables if present.
|
||||||
fn override_from_env(&mut self) -> Result<()> {
|
fn override_from_env(&mut self) -> Result<()> {
|
||||||
for (key, val) in env::vars() {
|
for (key, val) in env::vars() {
|
||||||
|
@ -371,10 +371,13 @@ impl RocketConfig {
|
||||||
|
|
||||||
/// Parses the configuration from the Rocket.toml file. Also overrides any
|
/// Parses the configuration from the Rocket.toml file. Also overrides any
|
||||||
/// values there with values from the environment.
|
/// values there with values from the environment.
|
||||||
fn parse<P: AsRef<Path>>(src: String, filename: P) -> Result<RocketConfig> {
|
fn parse<S, P>(src: S, filename: P) -> Result<FullConfig>
|
||||||
|
where S: Into<String>, P: AsRef<Path>
|
||||||
|
{
|
||||||
use self::ConfigError::ParseError;
|
use self::ConfigError::ParseError;
|
||||||
|
|
||||||
// Parse the source as TOML, if possible.
|
// Parse the source as TOML, if possible.
|
||||||
|
let src = src.into();
|
||||||
let path = filename.as_ref().to_path_buf();
|
let path = filename.as_ref().to_path_buf();
|
||||||
let table = match src.parse::<toml::Value>() {
|
let table = match src.parse::<toml::Value>() {
|
||||||
Ok(toml::Value::Table(table)) => table,
|
Ok(toml::Value::Table(table)) => table,
|
||||||
|
@ -386,7 +389,7 @@ impl RocketConfig {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create a config with the defaults; set the env to the active one.
|
// Create a config with the defaults; set the env to the active one.
|
||||||
let mut config = RocketConfig::active_default_from(Some(filename.as_ref()))?;
|
let mut config = FullConfig::active_default(filename.as_ref())?;
|
||||||
|
|
||||||
// Store all of the global overrides, if any, for later use.
|
// Store all of the global overrides, if any, for later use.
|
||||||
let mut global = None;
|
let mut global = None;
|
||||||
|
@ -422,57 +425,16 @@ impl RocketConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Override any variables from the environment.
|
|
||||||
config.override_from_env()?;
|
|
||||||
|
|
||||||
Ok(config)
|
Ok(config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the active configuration and whether this call initialized the
|
|
||||||
/// configuration. The configuration can only be initialized once.
|
|
||||||
///
|
|
||||||
/// Initializes the global RocketConfig by reading the Rocket config file from
|
|
||||||
/// the current directory or any of its parents. Returns the active
|
|
||||||
/// configuration, which is determined by the config env variable. If there as a
|
|
||||||
/// problem parsing the configuration, the error is printed and the program is
|
|
||||||
/// aborted. If there an I/O issue reading the config file, a warning is printed
|
|
||||||
/// and the default configuration is used. If there is no config file, the
|
|
||||||
/// default configuration is used.
|
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// If there is a problem, prints a nice error message and bails.
|
|
||||||
pub(crate) fn init() -> Config {
|
|
||||||
let bail = |e: ConfigError| -> ! {
|
|
||||||
logger::init(LoggingLevel::Debug);
|
|
||||||
e.pretty_print();
|
|
||||||
process::exit(1)
|
|
||||||
};
|
|
||||||
|
|
||||||
use self::ConfigError::*;
|
|
||||||
let config = RocketConfig::read().unwrap_or_else(|e| {
|
|
||||||
match e {
|
|
||||||
| ParseError(..) | BadEntry(..) | BadEnv(..) | BadType(..) | Io(..)
|
|
||||||
| BadFilePath(..) | BadEnvVal(..) | UnknownKey(..)
|
|
||||||
| Missing(..) => bail(e),
|
|
||||||
IoError => warn!("Failed reading Rocket.toml. Using defaults."),
|
|
||||||
NotFound => { /* try using the default below */ }
|
|
||||||
}
|
|
||||||
|
|
||||||
RocketConfig::active_default().unwrap_or_else(|e| bail(e))
|
|
||||||
});
|
|
||||||
|
|
||||||
// FIXME: Should probably store all of the config.
|
|
||||||
config.active().clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use super::{RocketConfig, Config, ConfigError, ConfigBuilder};
|
use super::{FullConfig, Config, ConfigError, ConfigBuilder};
|
||||||
use super::{Environment, GLOBAL_ENV_NAME};
|
use super::{Environment, GLOBAL_ENV_NAME};
|
||||||
use super::environment::CONFIG_ENV;
|
use super::environment::CONFIG_ENV;
|
||||||
use super::Environment::*;
|
use super::Environment::*;
|
||||||
|
@ -505,8 +467,10 @@ mod test {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn active_default() -> Result<RocketConfig> {
|
fn active_default() -> Result<FullConfig> {
|
||||||
RocketConfig::active_default()
|
let mut config = FullConfig::active_default(None)?;
|
||||||
|
config.override_from_env()?;
|
||||||
|
Ok(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_config(env: Environment) -> ConfigBuilder {
|
fn default_config(env: Environment) -> ConfigBuilder {
|
||||||
|
@ -560,7 +524,7 @@ mod test {
|
||||||
let toml_table = format!("[{}]\n", env);
|
let toml_table = format!("[{}]\n", env);
|
||||||
let e_str = env.to_string();
|
let e_str = env.to_string();
|
||||||
let err = ConfigError::BadEntry(e_str, TEST_CONFIG_FILENAME.into());
|
let err = ConfigError::BadEntry(e_str, TEST_CONFIG_FILENAME.into());
|
||||||
assert!(RocketConfig::parse(toml_table, TEST_CONFIG_FILENAME)
|
assert!(FullConfig::parse(toml_table, TEST_CONFIG_FILENAME)
|
||||||
.err().map_or(false, |e| e == err));
|
.err().map_or(false, |e| e == err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -596,21 +560,21 @@ mod test {
|
||||||
|
|
||||||
expected.environment = Development;
|
expected.environment = Development;
|
||||||
let dev_config = ["[dev]", config_str].join("\n");
|
let dev_config = ["[dev]", config_str].join("\n");
|
||||||
let parsed = RocketConfig::parse(dev_config, TEST_CONFIG_FILENAME);
|
let parsed = FullConfig::parse(dev_config, TEST_CONFIG_FILENAME);
|
||||||
check_config!(Development, parsed, expected.clone());
|
check_config!(Development, parsed, expected.clone());
|
||||||
check_config!(Staging, parsed, default_config(Staging));
|
check_config!(Staging, parsed, default_config(Staging));
|
||||||
check_config!(Production, parsed, default_config(Production));
|
check_config!(Production, parsed, default_config(Production));
|
||||||
|
|
||||||
expected.environment = Staging;
|
expected.environment = Staging;
|
||||||
let stage_config = ["[stage]", config_str].join("\n");
|
let stage_config = ["[stage]", config_str].join("\n");
|
||||||
let parsed = RocketConfig::parse(stage_config, TEST_CONFIG_FILENAME);
|
let parsed = FullConfig::parse(stage_config, TEST_CONFIG_FILENAME);
|
||||||
check_config!(Staging, parsed, expected.clone());
|
check_config!(Staging, parsed, expected.clone());
|
||||||
check_config!(Development, parsed, default_config(Development));
|
check_config!(Development, parsed, default_config(Development));
|
||||||
check_config!(Production, parsed, default_config(Production));
|
check_config!(Production, parsed, default_config(Production));
|
||||||
|
|
||||||
expected.environment = Production;
|
expected.environment = Production;
|
||||||
let prod_config = ["[prod]", config_str].join("\n");
|
let prod_config = ["[prod]", config_str].join("\n");
|
||||||
let parsed = RocketConfig::parse(prod_config, TEST_CONFIG_FILENAME);
|
let parsed = FullConfig::parse(prod_config, TEST_CONFIG_FILENAME);
|
||||||
check_config!(Production, parsed, expected);
|
check_config!(Production, parsed, expected);
|
||||||
check_config!(Development, parsed, default_config(Development));
|
check_config!(Development, parsed, default_config(Development));
|
||||||
check_config!(Staging, parsed, default_config(Staging));
|
check_config!(Staging, parsed, default_config(Staging));
|
||||||
|
@ -622,35 +586,35 @@ mod test {
|
||||||
let _env_lock = ENV_LOCK.lock().unwrap();
|
let _env_lock = ENV_LOCK.lock().unwrap();
|
||||||
env::set_var(CONFIG_ENV, "dev");
|
env::set_var(CONFIG_ENV, "dev");
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(FullConfig::parse(r#"
|
||||||
[development]
|
[development]
|
||||||
address = "localhost"
|
address = "localhost"
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME), {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
default_config(Development).address("localhost")
|
default_config(Development).address("localhost")
|
||||||
});
|
});
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(FullConfig::parse(r#"
|
||||||
[development]
|
[development]
|
||||||
address = "127.0.0.1"
|
address = "127.0.0.1"
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME), {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
default_config(Development).address("127.0.0.1")
|
default_config(Development).address("127.0.0.1")
|
||||||
});
|
});
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(FullConfig::parse(r#"
|
||||||
[development]
|
[development]
|
||||||
address = "::"
|
address = "::"
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME), {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
default_config(Development).address("::")
|
default_config(Development).address("::")
|
||||||
});
|
});
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(FullConfig::parse(r#"
|
||||||
[dev]
|
[dev]
|
||||||
address = "2001:db8::370:7334"
|
address = "2001:db8::370:7334"
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME), {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
default_config(Development).address("2001:db8::370:7334")
|
default_config(Development).address("2001:db8::370:7334")
|
||||||
});
|
});
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(FullConfig::parse(r#"
|
||||||
[dev]
|
[dev]
|
||||||
address = "0.0.0.0"
|
address = "0.0.0.0"
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME), {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
|
@ -664,22 +628,22 @@ mod test {
|
||||||
let _env_lock = ENV_LOCK.lock().unwrap();
|
let _env_lock = ENV_LOCK.lock().unwrap();
|
||||||
env::remove_var(CONFIG_ENV);
|
env::remove_var(CONFIG_ENV);
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[development]
|
[development]
|
||||||
address = 0000
|
address = 0000
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[development]
|
[development]
|
||||||
address = true
|
address = true
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[development]
|
[development]
|
||||||
address = "........"
|
address = "........"
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[staging]
|
[staging]
|
||||||
address = "1.2.3.4:100"
|
address = "1.2.3.4:100"
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
@ -693,24 +657,24 @@ mod test {
|
||||||
let _env_lock = ENV_LOCK.lock().unwrap();
|
let _env_lock = ENV_LOCK.lock().unwrap();
|
||||||
env::set_var(CONFIG_ENV, "dev");
|
env::set_var(CONFIG_ENV, "dev");
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[staging]
|
[staging]
|
||||||
tls = { certs = "some/path.pem", key = "some/key.pem" }
|
tls = { certs = "some/path.pem", key = "some/key.pem" }
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_ok());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_ok());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[staging.tls]
|
[staging.tls]
|
||||||
certs = "some/path.pem"
|
certs = "some/path.pem"
|
||||||
key = "some/key.pem"
|
key = "some/key.pem"
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_ok());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_ok());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[global.tls]
|
[global.tls]
|
||||||
certs = "some/path.pem"
|
certs = "some/path.pem"
|
||||||
key = "some/key.pem"
|
key = "some/key.pem"
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_ok());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_ok());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[global]
|
[global]
|
||||||
tls = { certs = "some/path.pem", key = "some/key.pem" }
|
tls = { certs = "some/path.pem", key = "some/key.pem" }
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_ok());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_ok());
|
||||||
|
@ -722,22 +686,22 @@ mod test {
|
||||||
let _env_lock = ENV_LOCK.lock().unwrap();
|
let _env_lock = ENV_LOCK.lock().unwrap();
|
||||||
env::remove_var(CONFIG_ENV);
|
env::remove_var(CONFIG_ENV);
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[development]
|
[development]
|
||||||
tls = "hello"
|
tls = "hello"
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[development]
|
[development]
|
||||||
tls = { certs = "some/path.pem" }
|
tls = { certs = "some/path.pem" }
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[development]
|
[development]
|
||||||
tls = { certs = "some/path.pem", key = "some/key.pem", extra = "bah" }
|
tls = { certs = "some/path.pem", key = "some/key.pem", extra = "bah" }
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[staging]
|
[staging]
|
||||||
tls = { cert = "some/path.pem", key = "some/key.pem" }
|
tls = { cert = "some/path.pem", key = "some/key.pem" }
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
@ -749,21 +713,21 @@ mod test {
|
||||||
let _env_lock = ENV_LOCK.lock().unwrap();
|
let _env_lock = ENV_LOCK.lock().unwrap();
|
||||||
env::set_var(CONFIG_ENV, "stage");
|
env::set_var(CONFIG_ENV, "stage");
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(FullConfig::parse(r#"
|
||||||
[stage]
|
[stage]
|
||||||
port = 100
|
port = 100
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME), {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
default_config(Staging).port(100)
|
default_config(Staging).port(100)
|
||||||
});
|
});
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(FullConfig::parse(r#"
|
||||||
[stage]
|
[stage]
|
||||||
port = 6000
|
port = 6000
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME), {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
default_config(Staging).port(6000)
|
default_config(Staging).port(6000)
|
||||||
});
|
});
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(FullConfig::parse(r#"
|
||||||
[stage]
|
[stage]
|
||||||
port = 65535
|
port = 65535
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME), {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
|
@ -777,27 +741,27 @@ mod test {
|
||||||
let _env_lock = ENV_LOCK.lock().unwrap();
|
let _env_lock = ENV_LOCK.lock().unwrap();
|
||||||
env::remove_var(CONFIG_ENV);
|
env::remove_var(CONFIG_ENV);
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[development]
|
[development]
|
||||||
port = true
|
port = true
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[production]
|
[production]
|
||||||
port = "hello"
|
port = "hello"
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[staging]
|
[staging]
|
||||||
port = -1
|
port = -1
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[staging]
|
[staging]
|
||||||
port = 65536
|
port = 65536
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[staging]
|
[staging]
|
||||||
port = 105836
|
port = 105836
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
@ -809,21 +773,21 @@ mod test {
|
||||||
let _env_lock = ENV_LOCK.lock().unwrap();
|
let _env_lock = ENV_LOCK.lock().unwrap();
|
||||||
env::set_var(CONFIG_ENV, "stage");
|
env::set_var(CONFIG_ENV, "stage");
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(FullConfig::parse(r#"
|
||||||
[stage]
|
[stage]
|
||||||
workers = 1
|
workers = 1
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME), {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
default_config(Staging).workers(1)
|
default_config(Staging).workers(1)
|
||||||
});
|
});
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(FullConfig::parse(r#"
|
||||||
[stage]
|
[stage]
|
||||||
workers = 300
|
workers = 300
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME), {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
default_config(Staging).workers(300)
|
default_config(Staging).workers(300)
|
||||||
});
|
});
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(FullConfig::parse(r#"
|
||||||
[stage]
|
[stage]
|
||||||
workers = 65535
|
workers = 65535
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME), {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
|
@ -837,27 +801,27 @@ mod test {
|
||||||
let _env_lock = ENV_LOCK.lock().unwrap();
|
let _env_lock = ENV_LOCK.lock().unwrap();
|
||||||
env::remove_var(CONFIG_ENV);
|
env::remove_var(CONFIG_ENV);
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[development]
|
[development]
|
||||||
workers = true
|
workers = true
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[production]
|
[production]
|
||||||
workers = "hello"
|
workers = "hello"
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[staging]
|
[staging]
|
||||||
workers = -1
|
workers = -1
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[staging]
|
[staging]
|
||||||
workers = 65536
|
workers = 65536
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[staging]
|
[staging]
|
||||||
workers = 105836
|
workers = 105836
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
@ -869,28 +833,28 @@ mod test {
|
||||||
let _env_lock = ENV_LOCK.lock().unwrap();
|
let _env_lock = ENV_LOCK.lock().unwrap();
|
||||||
env::set_var(CONFIG_ENV, "stage");
|
env::set_var(CONFIG_ENV, "stage");
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(FullConfig::parse(r#"
|
||||||
[stage]
|
[stage]
|
||||||
keep_alive = 10
|
keep_alive = 10
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME), {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
default_config(Staging).keep_alive(10)
|
default_config(Staging).keep_alive(10)
|
||||||
});
|
});
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(FullConfig::parse(r#"
|
||||||
[stage]
|
[stage]
|
||||||
keep_alive = 0
|
keep_alive = 0
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME), {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
default_config(Staging).keep_alive(0)
|
default_config(Staging).keep_alive(0)
|
||||||
});
|
});
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(FullConfig::parse(r#"
|
||||||
[stage]
|
[stage]
|
||||||
keep_alive = 348
|
keep_alive = 348
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME), {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
default_config(Staging).keep_alive(348)
|
default_config(Staging).keep_alive(348)
|
||||||
});
|
});
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(FullConfig::parse(r#"
|
||||||
[stage]
|
[stage]
|
||||||
keep_alive = 0
|
keep_alive = 0
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME), {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
|
@ -904,22 +868,22 @@ mod test {
|
||||||
let _env_lock = ENV_LOCK.lock().unwrap();
|
let _env_lock = ENV_LOCK.lock().unwrap();
|
||||||
env::remove_var(CONFIG_ENV);
|
env::remove_var(CONFIG_ENV);
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[dev]
|
[dev]
|
||||||
keep_alive = true
|
keep_alive = true
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[dev]
|
[dev]
|
||||||
keep_alive = -10
|
keep_alive = -10
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[dev]
|
[dev]
|
||||||
keep_alive = "Some(10)"
|
keep_alive = "Some(10)"
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[dev]
|
[dev]
|
||||||
keep_alive = 4294967296
|
keep_alive = 4294967296
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
@ -931,7 +895,7 @@ mod test {
|
||||||
let _env_lock = ENV_LOCK.lock().unwrap();
|
let _env_lock = ENV_LOCK.lock().unwrap();
|
||||||
env::set_var(CONFIG_ENV, "stage");
|
env::set_var(CONFIG_ENV, "stage");
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(FullConfig::parse(r#"
|
||||||
[stage]
|
[stage]
|
||||||
log = "normal"
|
log = "normal"
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME), {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
|
@ -939,21 +903,21 @@ mod test {
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(FullConfig::parse(r#"
|
||||||
[stage]
|
[stage]
|
||||||
log = "debug"
|
log = "debug"
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME), {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
default_config(Staging).log_level(LoggingLevel::Debug)
|
default_config(Staging).log_level(LoggingLevel::Debug)
|
||||||
});
|
});
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(FullConfig::parse(r#"
|
||||||
[stage]
|
[stage]
|
||||||
log = "critical"
|
log = "critical"
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME), {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
default_config(Staging).log_level(LoggingLevel::Critical)
|
default_config(Staging).log_level(LoggingLevel::Critical)
|
||||||
});
|
});
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(FullConfig::parse(r#"
|
||||||
[stage]
|
[stage]
|
||||||
log = "off"
|
log = "off"
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME), {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
|
@ -967,17 +931,17 @@ mod test {
|
||||||
let _env_lock = ENV_LOCK.lock().unwrap();
|
let _env_lock = ENV_LOCK.lock().unwrap();
|
||||||
env::remove_var(CONFIG_ENV);
|
env::remove_var(CONFIG_ENV);
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[dev]
|
[dev]
|
||||||
log = false
|
log = false
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[development]
|
[development]
|
||||||
log = 0
|
log = 0
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[prod]
|
[prod]
|
||||||
log = "no"
|
log = "no"
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
@ -989,7 +953,7 @@ mod test {
|
||||||
let _env_lock = ENV_LOCK.lock().unwrap();
|
let _env_lock = ENV_LOCK.lock().unwrap();
|
||||||
env::set_var(CONFIG_ENV, "stage");
|
env::set_var(CONFIG_ENV, "stage");
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(FullConfig::parse(r#"
|
||||||
[stage]
|
[stage]
|
||||||
secret_key = "TpUiXK2d/v5DFxJnWL12suJKPExKR8h9zd/o+E7SU+0="
|
secret_key = "TpUiXK2d/v5DFxJnWL12suJKPExKR8h9zd/o+E7SU+0="
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME), {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
|
@ -998,7 +962,7 @@ mod test {
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(FullConfig::parse(r#"
|
||||||
[stage]
|
[stage]
|
||||||
secret_key = "jTyprDberFUiUFsJ3vcb1XKsYHWNBRvWAnXTlbTgGFU="
|
secret_key = "jTyprDberFUiUFsJ3vcb1XKsYHWNBRvWAnXTlbTgGFU="
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME), {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
|
@ -1014,17 +978,17 @@ mod test {
|
||||||
let _env_lock = ENV_LOCK.lock().unwrap();
|
let _env_lock = ENV_LOCK.lock().unwrap();
|
||||||
env::remove_var(CONFIG_ENV);
|
env::remove_var(CONFIG_ENV);
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[dev]
|
[dev]
|
||||||
secret_key = true
|
secret_key = true
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[dev]
|
[dev]
|
||||||
secret_key = 1283724897238945234897
|
secret_key = 1283724897238945234897
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[dev]
|
[dev]
|
||||||
secret_key = "abcv"
|
secret_key = "abcv"
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
@ -1036,16 +1000,16 @@ mod test {
|
||||||
let _env_lock = ENV_LOCK.lock().unwrap();
|
let _env_lock = ENV_LOCK.lock().unwrap();
|
||||||
env::remove_var(CONFIG_ENV);
|
env::remove_var(CONFIG_ENV);
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[dev
|
[dev
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[dev]
|
[dev]
|
||||||
1. = 2
|
1. = 2
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(FullConfig::parse(r#"
|
||||||
[dev]
|
[dev]
|
||||||
secret_key = "abcv" = other
|
secret_key = "abcv" = other
|
||||||
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
@ -1060,21 +1024,21 @@ mod test {
|
||||||
for env in &Environment::ALL {
|
for env in &Environment::ALL {
|
||||||
env::set_var(CONFIG_ENV, env.to_string());
|
env::set_var(CONFIG_ENV, env.to_string());
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(format!(r#"
|
check_config!(FullConfig::parse(format!(r#"
|
||||||
[{}]
|
[{}]
|
||||||
address = "::1"
|
address = "::1"
|
||||||
"#, GLOBAL_ENV_NAME), TEST_CONFIG_FILENAME), {
|
"#, GLOBAL_ENV_NAME), TEST_CONFIG_FILENAME), {
|
||||||
default_config(*env).address("::1")
|
default_config(*env).address("::1")
|
||||||
});
|
});
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(format!(r#"
|
check_config!(FullConfig::parse(format!(r#"
|
||||||
[{}]
|
[{}]
|
||||||
database = "mysql"
|
database = "mysql"
|
||||||
"#, GLOBAL_ENV_NAME), TEST_CONFIG_FILENAME), {
|
"#, GLOBAL_ENV_NAME), TEST_CONFIG_FILENAME), {
|
||||||
default_config(*env).extra("database", "mysql")
|
default_config(*env).extra("database", "mysql")
|
||||||
});
|
});
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(format!(r#"
|
check_config!(FullConfig::parse(format!(r#"
|
||||||
[{}]
|
[{}]
|
||||||
port = 3980
|
port = 3980
|
||||||
"#, GLOBAL_ENV_NAME), TEST_CONFIG_FILENAME), {
|
"#, GLOBAL_ENV_NAME), TEST_CONFIG_FILENAME), {
|
||||||
|
@ -1083,6 +1047,19 @@ mod test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! check_value {
|
||||||
|
($key:expr, $val:expr, $config:expr) => (
|
||||||
|
match $key {
|
||||||
|
"log" => assert_eq!($config.log_level, $val.parse().unwrap()),
|
||||||
|
"port" => assert_eq!($config.port, $val.parse().unwrap()),
|
||||||
|
"address" => assert_eq!($config.address, $val),
|
||||||
|
"extra_extra" => assert_eq!($config.get_bool($key).unwrap(), true),
|
||||||
|
"workers" => assert_eq!($config.workers, $val.parse().unwrap()),
|
||||||
|
_ => panic!("Unexpected key: {}", $key)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_env_override() {
|
fn test_env_override() {
|
||||||
// Take the lock so changing the environment doesn't cause races.
|
// Take the lock so changing the environment doesn't cause races.
|
||||||
|
@ -1093,33 +1070,22 @@ mod test {
|
||||||
("address", "1.2.3.4"), ("EXTRA_EXTRA", "true"), ("workers", "3")
|
("address", "1.2.3.4"), ("EXTRA_EXTRA", "true"), ("workers", "3")
|
||||||
];
|
];
|
||||||
|
|
||||||
let check_value = |key: &str, val: &str, config: &Config| {
|
|
||||||
match key {
|
|
||||||
"log" => assert_eq!(config.log_level, val.parse().unwrap()),
|
|
||||||
"port" => assert_eq!(config.port, val.parse().unwrap()),
|
|
||||||
"address" => assert_eq!(config.address, val),
|
|
||||||
"extra_extra" => assert_eq!(config.get_bool(key).unwrap(), true),
|
|
||||||
"workers" => assert_eq!(config.workers, val.parse().unwrap()),
|
|
||||||
_ => panic!("Unexpected key: {}", key)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check that setting the environment variable actually changes the
|
// Check that setting the environment variable actually changes the
|
||||||
// config for the default active and nonactive environments.
|
// config for the default active and nonactive environments.
|
||||||
for &(key, val) in &pairs {
|
for &(key, val) in &pairs {
|
||||||
env::set_var(format!("ROCKET_{}", key), val);
|
env::set_var(format!("ROCKET_{}", key), val);
|
||||||
|
|
||||||
let rconfig = active_default().unwrap();
|
|
||||||
// Check that it overrides the active config.
|
// Check that it overrides the active config.
|
||||||
for env in &Environment::ALL {
|
for env in &Environment::ALL {
|
||||||
env::set_var(CONFIG_ENV, env.to_string());
|
env::set_var(CONFIG_ENV, env.to_string());
|
||||||
let rconfig = active_default().unwrap();
|
let rconfig = active_default().unwrap();
|
||||||
check_value(&*key.to_lowercase(), val, rconfig.active());
|
check_value!(&*key.to_lowercase(), val, rconfig.active());
|
||||||
}
|
}
|
||||||
|
|
||||||
// And non-active configs.
|
// And non-active configs.
|
||||||
|
let rconfig = active_default().unwrap();
|
||||||
for env in &Environment::ALL {
|
for env in &Environment::ALL {
|
||||||
check_value(&*key.to_lowercase(), val, rconfig.get(*env));
|
check_value!(&*key.to_lowercase(), val, rconfig.get(*env));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1145,19 +1111,20 @@ mod test {
|
||||||
port = 7810
|
port = 7810
|
||||||
workers = 21
|
workers = 21
|
||||||
log = "normal"
|
log = "normal"
|
||||||
"#.to_string();
|
"#;
|
||||||
|
|
||||||
// Check that setting the environment variable actually changes the
|
// Check that setting the environment variable actually changes the
|
||||||
// config for the default active environments.
|
// config for the default active environments.
|
||||||
for &(key, val) in &pairs {
|
for &(key, val) in &pairs {
|
||||||
env::set_var(format!("ROCKET_{}", key), val);
|
env::set_var(format!("ROCKET_{}", key), val);
|
||||||
|
|
||||||
let r = RocketConfig::parse(toml.clone(), TEST_CONFIG_FILENAME).unwrap();
|
let mut r = FullConfig::parse(toml, TEST_CONFIG_FILENAME).unwrap();
|
||||||
check_value(&*key.to_lowercase(), val, r.active());
|
r.override_from_env().unwrap();
|
||||||
|
check_value!(&*key.to_lowercase(), val, r.active());
|
||||||
|
|
||||||
// And non-active configs.
|
// And non-active configs.
|
||||||
for env in &Environment::ALL {
|
for env in &Environment::ALL {
|
||||||
check_value(&*key.to_lowercase(), val, r.get(*env));
|
check_value!(&*key.to_lowercase(), val, r.get(*env));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ use state::Container;
|
||||||
|
|
||||||
use crate::{logger, handler};
|
use crate::{logger, handler};
|
||||||
use crate::ext::ReadExt;
|
use crate::ext::ReadExt;
|
||||||
use crate::config::{self, Config, LoggedValue};
|
use crate::config::{Config, FullConfig, ConfigError, LoggedValue};
|
||||||
use crate::request::{Request, FormItems};
|
use crate::request::{Request, FormItems};
|
||||||
use crate::data::Data;
|
use crate::data::Data;
|
||||||
use crate::response::{Body, Response};
|
use crate::response::{Body, Response};
|
||||||
|
@ -344,16 +344,17 @@ impl Rocket {
|
||||||
|
|
||||||
/// Create a new `Rocket` application using the configuration information in
|
/// Create a new `Rocket` application using the configuration information in
|
||||||
/// `Rocket.toml`. If the file does not exist or if there is an I/O error
|
/// `Rocket.toml`. If the file does not exist or if there is an I/O error
|
||||||
/// reading the file, the defaults are used. See the [`config`]
|
/// reading the file, the defaults are used. See the
|
||||||
/// documentation for more information on defaults.
|
/// [`config`](crate::config) documentation for more information on
|
||||||
|
/// defaults.
|
||||||
///
|
///
|
||||||
/// This method is typically called through the
|
/// This method is typically called through the
|
||||||
/// [`rocket::ignite()`](crate::ignite) alias.
|
/// [`rocket::ignite()`](crate::ignite) alias.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// If there is an error parsing the `Rocket.toml` file, this functions
|
/// If there is an error reading configuration sources, this function prints
|
||||||
/// prints a nice error message and then exits the process.
|
/// a nice error message and then exits the process.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -362,10 +363,22 @@ impl Rocket {
|
||||||
/// rocket::ignite()
|
/// rocket::ignite()
|
||||||
/// # };
|
/// # };
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
|
||||||
pub fn ignite() -> Rocket {
|
pub fn ignite() -> Rocket {
|
||||||
// Note: init() will exit the process under config errors.
|
Config::read()
|
||||||
Rocket::configured(config::init())
|
.or_else(|e| match e {
|
||||||
|
ConfigError::IoError => {
|
||||||
|
warn!("Failed to read 'Rocket.toml'. Using defaults.");
|
||||||
|
Ok(FullConfig::active_default(None)?.take_active())
|
||||||
|
}
|
||||||
|
ConfigError::NotFound => Ok(FullConfig::active_default(None)?.take_active()),
|
||||||
|
_ => Err(e)
|
||||||
|
})
|
||||||
|
.map(Rocket::configured)
|
||||||
|
.unwrap_or_else(|e: ConfigError| {
|
||||||
|
logger::init(logger::LoggingLevel::Debug);
|
||||||
|
e.pretty_print();
|
||||||
|
std::process::exit(1)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new `Rocket` application using the supplied custom
|
/// Creates a new `Rocket` application using the supplied custom
|
||||||
|
|
Loading…
Reference in New Issue