mirror of https://github.com/rwf2/Rocket.git
Add `config::get()`, for global config access. Use it for `Template`.
This commit is contained in:
parent
722f613686
commit
1323e7a420
|
@ -16,7 +16,7 @@ use self::glob::glob;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use rocket::Rocket;
|
use rocket::config;
|
||||||
use rocket::response::{Content, ResponseOutcome, Responder};
|
use rocket::response::{Content, ResponseOutcome, Responder};
|
||||||
use rocket::http::hyper::FreshHyperResponse;
|
use rocket::http::hyper::FreshHyperResponse;
|
||||||
use rocket::http::{ContentType, StatusCode};
|
use rocket::http::{ContentType, StatusCode};
|
||||||
|
@ -114,11 +114,22 @@ pub struct TemplateInfo {
|
||||||
data_type: Option<String>
|
data_type: Option<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DEFAULT_TEMPLATE_DIR: &'static str = "templates";
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref TEMPLATES: HashMap<String, TemplateInfo> = discover_templates();
|
static ref TEMPLATES: HashMap<String, TemplateInfo> = discover_templates();
|
||||||
// FIXME: Ensure template_dir is an absolute path starting at crate root.
|
static ref TEMPLATE_DIR: String = {
|
||||||
static ref TEMPLATE_DIR: String =
|
config::active().map(|config| {
|
||||||
Rocket::config("template_dir").unwrap_or("templates").to_string();
|
let dir = config.get_str("template_dir").map_err(|e| {
|
||||||
|
if !e.is_not_found() {
|
||||||
|
e.pretty_print();
|
||||||
|
warn_!("Using default directory '{}'", DEFAULT_TEMPLATE_DIR);
|
||||||
|
}
|
||||||
|
}).unwrap_or(DEFAULT_TEMPLATE_DIR);
|
||||||
|
|
||||||
|
config.root().join(dir).to_string_lossy().into_owned()
|
||||||
|
}).unwrap_or("templates".to_string())
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Template {
|
impl Template {
|
||||||
|
@ -133,6 +144,7 @@ impl Template {
|
||||||
let template = TEMPLATES.get(name);
|
let template = TEMPLATES.get(name);
|
||||||
if template.is_none() {
|
if template.is_none() {
|
||||||
error_!("Template '{}' does not exist.", name);
|
error_!("Template '{}' does not exist.", name);
|
||||||
|
info_!("Searched in '{}'.", *TEMPLATE_DIR);
|
||||||
return Template(None, None);
|
return Template(None, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
address = "localhost"
|
address = "localhost"
|
||||||
port = 8000
|
port = 8000
|
||||||
log = "normal"
|
log = "normal"
|
||||||
|
hi = "Hello!"
|
||||||
|
is_extra = true
|
||||||
|
|
||||||
[staging]
|
[staging]
|
||||||
address = "0.0.0.0"
|
address = "0.0.0.0"
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
# TODO: Allow a `global` pseudo-environment that overrides all environments.
|
||||||
|
# [global]
|
||||||
|
# template_dir = "static"
|
||||||
|
|
||||||
|
[dev]
|
||||||
|
template_dir = "static"
|
||||||
|
|
||||||
|
[stage]
|
||||||
|
template_dir = "static"
|
||||||
|
|
||||||
|
[prod]
|
||||||
|
template_dir = "static"
|
|
@ -1,8 +1,9 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::net::ToSocketAddrs;
|
use std::net::ToSocketAddrs;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
use super::Environment::*;
|
use config::Environment::*;
|
||||||
use super::Environment;
|
use config::{self, Environment, ConfigError};
|
||||||
|
|
||||||
use logger::LoggingLevel;
|
use logger::LoggingLevel;
|
||||||
use toml::Value;
|
use toml::Value;
|
||||||
|
@ -13,28 +14,28 @@ pub struct Config {
|
||||||
pub port: usize,
|
pub port: usize,
|
||||||
pub log_level: LoggingLevel,
|
pub log_level: LoggingLevel,
|
||||||
pub session_key: Option<String>,
|
pub session_key: Option<String>,
|
||||||
pub extra: HashMap<String, Value>,
|
pub env: Environment,
|
||||||
|
extra: HashMap<String, Value>,
|
||||||
|
filename: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! parse {
|
macro_rules! parse {
|
||||||
($val:expr, as_str) => (
|
($conf:expr, $name:expr, $val:expr, $method:ident, $expect: expr) => (
|
||||||
match $val.as_str() {
|
$val.$method().ok_or_else(|| {
|
||||||
Some(v) => v,
|
$conf.bad_type($name, $val, $expect)
|
||||||
None => return Err("a string")
|
})
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
($val:expr, as_integer) => (
|
|
||||||
match $val.as_integer() {
|
|
||||||
Some(v) => v,
|
|
||||||
None => return Err("an integer")
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
pub fn default_for(env: Environment) -> Config {
|
pub fn default_for(env: Environment, filename: &str) -> config::Result<Config> {
|
||||||
match env {
|
let file_path = Path::new(filename);
|
||||||
|
if file_path.parent().is_none() {
|
||||||
|
return Err(ConfigError::BadFilePath(filename.to_string(),
|
||||||
|
"Configuration files must be rooted in a directory."));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(match env {
|
||||||
Development => {
|
Development => {
|
||||||
Config {
|
Config {
|
||||||
address: "localhost".to_string(),
|
address: "localhost".to_string(),
|
||||||
|
@ -42,6 +43,8 @@ impl Config {
|
||||||
log_level: LoggingLevel::Normal,
|
log_level: LoggingLevel::Normal,
|
||||||
session_key: None,
|
session_key: None,
|
||||||
extra: HashMap::new(),
|
extra: HashMap::new(),
|
||||||
|
env: env,
|
||||||
|
filename: filename.to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Staging => {
|
Staging => {
|
||||||
|
@ -51,6 +54,8 @@ impl Config {
|
||||||
log_level: LoggingLevel::Normal,
|
log_level: LoggingLevel::Normal,
|
||||||
session_key: None,
|
session_key: None,
|
||||||
extra: HashMap::new(),
|
extra: HashMap::new(),
|
||||||
|
env: env,
|
||||||
|
filename: filename.to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Production => {
|
Production => {
|
||||||
|
@ -60,44 +65,118 @@ impl Config {
|
||||||
log_level: LoggingLevel::Critical,
|
log_level: LoggingLevel::Critical,
|
||||||
session_key: None,
|
session_key: None,
|
||||||
extra: HashMap::new(),
|
extra: HashMap::new(),
|
||||||
|
env: env,
|
||||||
|
filename: filename.to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set(&mut self, name: &str, value: &Value) -> Result<(), &'static str> {
|
#[inline(always)]
|
||||||
|
fn bad_type(&self, name: &str, val: &Value, expect: &'static str) -> ConfigError {
|
||||||
|
let id = format!("{}.{}", self.env, name);
|
||||||
|
ConfigError::BadType(id, expect, val.type_str(), self.filename.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set(&mut self, name: &str, val: &Value) -> config::Result<()> {
|
||||||
if name == "address" {
|
if name == "address" {
|
||||||
let address_str = parse!(value, as_str).to_string();
|
let address_str = parse!(self, name, val, as_str, "a string")?;
|
||||||
if address_str.contains(":") {
|
if address_str.contains(":") {
|
||||||
return Err("an IP address with no port")
|
return Err(self.bad_type(name, val, "an IP address with no port"));
|
||||||
} else if format!("{}:{}", address_str, 80).to_socket_addrs().is_err() {
|
} else if format!("{}:{}", address_str, 80).to_socket_addrs().is_err() {
|
||||||
return Err("a valid IP address")
|
return Err(self.bad_type(name, val, "a valid IP address"));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.address = address_str;
|
self.address = address_str.to_string();
|
||||||
} else if name == "port" {
|
} else if name == "port" {
|
||||||
let port = parse!(value, as_integer);
|
let port = parse!(self, name, val, as_integer, "an integer")?;
|
||||||
if port < 0 {
|
if port < 0 {
|
||||||
return Err("an unsigned integer");
|
return Err(self.bad_type(name, val, "an unsigned integer"));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.port = port as usize;
|
self.port = port as usize;
|
||||||
} else if name == "session_key" {
|
} else if name == "session_key" {
|
||||||
let key = parse!(value, as_str);
|
let key = parse!(self, name, val, as_str, "a string")?;
|
||||||
if key.len() != 32 {
|
if key.len() != 32 {
|
||||||
return Err("a 192-bit base64 encoded string")
|
return Err(self.bad_type(name, val, "a 192-bit base64 string"));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.session_key = Some(key.to_string());
|
self.session_key = Some(key.to_string());
|
||||||
} else if name == "log" {
|
} else if name == "log" {
|
||||||
self.log_level = match parse!(value, as_str).parse() {
|
let level_str = parse!(self, name, val, as_str, "a string")?;
|
||||||
|
self.log_level = match level_str.parse() {
|
||||||
Ok(level) => level,
|
Ok(level) => level,
|
||||||
Err(_) => return Err("log level ('normal', 'critical', 'debug')"),
|
Err(_) => return Err(self.bad_type(name, val,
|
||||||
|
"log level ('normal', 'critical', 'debug')"))
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
self.extra.insert(name.into(), value.clone());
|
self.extra.insert(name.into(), val.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_str<'a>(&'a self, name: &str) -> config::Result<&'a str> {
|
||||||
|
let value = self.extra.get(name).ok_or_else(|| ConfigError::NotFound)?;
|
||||||
|
parse!(self, name, value, as_str, "a string")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_int<'a>(&'a self, name: &str) -> config::Result<i64> {
|
||||||
|
let value = self.extra.get(name).ok_or_else(|| ConfigError::NotFound)?;
|
||||||
|
parse!(self, name, value, as_integer, "an integer")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_bool<'a>(&'a self, name: &str) -> config::Result<bool> {
|
||||||
|
let value = self.extra.get(name).ok_or_else(|| ConfigError::NotFound)?;
|
||||||
|
parse!(self, name, value, as_bool, "a boolean")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_float<'a>(&'a self, name: &str) -> config::Result<f64> {
|
||||||
|
let value = self.extra.get(name).ok_or_else(|| ConfigError::NotFound)?;
|
||||||
|
parse!(self, name, value, as_float, "a float")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn root(&self) -> &Path {
|
||||||
|
match Path::new(self.filename.as_str()).parent() {
|
||||||
|
Some(parent) => &parent,
|
||||||
|
None => panic!("root(): filename {} has no parent", self.filename)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn extras<'a>(&'a self) -> impl Iterator<Item=(&'a String, &'a Value)> {
|
||||||
|
self.extra.iter()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Builder pattern below, mostly for testing.
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn address(mut self, var: String) -> Self {
|
||||||
|
self.address = var;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn port(mut self, var: usize) -> Self {
|
||||||
|
self.port = var;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn log_level(mut self, var: LoggingLevel) -> Self {
|
||||||
|
self.log_level = var;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn session_key(mut self, var: String) -> Self {
|
||||||
|
self.session_key = Some(var);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn env(mut self, var: Environment) -> Self {
|
||||||
|
self.env = var;
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@ pub enum ConfigError {
|
||||||
BadCWD,
|
BadCWD,
|
||||||
NotFound,
|
NotFound,
|
||||||
IOError,
|
IOError,
|
||||||
|
/// (path, reason)
|
||||||
|
BadFilePath(String, &'static str),
|
||||||
/// (environment_name)
|
/// (environment_name)
|
||||||
BadEnv(String),
|
BadEnv(String),
|
||||||
/// (environment_name, filename)
|
/// (environment_name, filename)
|
||||||
|
@ -35,6 +37,10 @@ impl ConfigError {
|
||||||
BadCWD => error!("couldn't get current working directory"),
|
BadCWD => error!("couldn't get current working directory"),
|
||||||
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"),
|
||||||
|
BadFilePath(ref path, ref reason) => {
|
||||||
|
error!("configuration file path '{}' is invalid", path);
|
||||||
|
info_!("{}", reason);
|
||||||
|
}
|
||||||
BadEntry(ref name, ref filename) => {
|
BadEntry(ref name, ref filename) => {
|
||||||
error!("[{}] is not a known configuration environment", name);
|
error!("[{}] is not a known configuration environment", name);
|
||||||
info_!("in {}", White.paint(filename));
|
info_!("in {}", White.paint(filename));
|
||||||
|
@ -63,4 +69,12 @@ impl ConfigError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_not_found(&self) -> bool {
|
||||||
|
use self::ConfigError::*;
|
||||||
|
match *self {
|
||||||
|
NotFound => true,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,12 @@ use self::config::Config;
|
||||||
use toml::{self, Table};
|
use toml::{self, Table};
|
||||||
use logger::{self, LoggingLevel};
|
use logger::{self, LoggingLevel};
|
||||||
|
|
||||||
|
static mut CONFIG: Option<RocketConfig> = None;
|
||||||
|
|
||||||
const CONFIG_FILENAME: &'static str = "Rocket.toml";
|
const CONFIG_FILENAME: &'static str = "Rocket.toml";
|
||||||
|
|
||||||
|
pub type Result<T> = ::std::result::Result<T, ConfigError>;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub struct RocketConfig {
|
pub struct RocketConfig {
|
||||||
pub active_env: Environment,
|
pub active_env: Environment,
|
||||||
|
@ -28,7 +32,7 @@ pub struct RocketConfig {
|
||||||
impl RocketConfig {
|
impl RocketConfig {
|
||||||
/// Iteratively search for `file` in `pwd` and its parents, returning the path
|
/// Iteratively search for `file` in `pwd` and its parents, returning the path
|
||||||
/// to the file or an Error::NoKey if the file couldn't be found.
|
/// to the file or an Error::NoKey if the file couldn't be found.
|
||||||
fn find() -> Result<PathBuf, ConfigError> {
|
fn find() -> Result<PathBuf> {
|
||||||
let cwd = env::current_dir().map_err(|_| ConfigError::BadCWD)?;
|
let cwd = env::current_dir().map_err(|_| ConfigError::BadCWD)?;
|
||||||
let mut current = cwd.as_path();
|
let mut current = cwd.as_path();
|
||||||
|
|
||||||
|
@ -47,26 +51,24 @@ impl RocketConfig {
|
||||||
Err(ConfigError::NotFound)
|
Err(ConfigError::NotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set(&mut self, env: Environment, kvs: &Table, filename: &str)
|
fn set(&mut self, env: Environment, kvs: &Table)
|
||||||
-> Result<(), ConfigError> {
|
-> Result<()> {
|
||||||
let config = self.config.entry(env).or_insert(Config::default_for(env));
|
let config = match self.config.get_mut(&env) {
|
||||||
|
Some(config) => config,
|
||||||
|
None => panic!("set(): {} config is missing.", env),
|
||||||
|
};
|
||||||
|
|
||||||
for (key, value) in kvs {
|
for (key, value) in kvs {
|
||||||
if let Err(expected) = config.set(key, value) {
|
config.set(key, value)?;
|
||||||
let name = format!("{}.{}", env, key);
|
|
||||||
return Err(ConfigError::BadType(
|
|
||||||
name, expected, value.type_str(), filename.to_string()
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, env: Environment) -> &Config {
|
pub fn get(&self, env: Environment) -> &Config {
|
||||||
if let Some(config) = self.config.get(&env) {
|
match self.config.get(&env) {
|
||||||
config
|
Some(config) => config,
|
||||||
} else {
|
None => panic!("get(): {} config is missing.", env),
|
||||||
panic!("No value from environment: {:?}", env);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +76,7 @@ impl RocketConfig {
|
||||||
self.get(self.active_env)
|
self.get(self.active_env)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse(src: String, filename: &str) -> Result<RocketConfig, ConfigError> {
|
fn parse(src: String, filename: &str) -> Result<RocketConfig> {
|
||||||
// Parse the source as TOML, if possible.
|
// Parse the source as TOML, if possible.
|
||||||
let mut parser = toml::Parser::new(&src);
|
let mut parser = toml::Parser::new(&src);
|
||||||
let toml = parser.parse().ok_or(ConfigError::ParseError(
|
let toml = parser.parse().ok_or(ConfigError::ParseError(
|
||||||
|
@ -88,7 +90,7 @@ impl RocketConfig {
|
||||||
))?;
|
))?;
|
||||||
|
|
||||||
// Create a config with the defaults, but the set the env to the active
|
// Create a config with the defaults, but the set the env to the active
|
||||||
let mut config = RocketConfig::active_default()?;
|
let mut config = RocketConfig::active_default(filename)?;
|
||||||
|
|
||||||
// Parse the values from the TOML file.
|
// Parse the values from the TOML file.
|
||||||
for (entry, value) in toml {
|
for (entry, value) in toml {
|
||||||
|
@ -106,13 +108,13 @@ impl RocketConfig {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set the environment configuration from the kv pairs.
|
// Set the environment configuration from the kv pairs.
|
||||||
config.set(env, &kv_pairs, filename)?;
|
config.set(env, &kv_pairs)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(config)
|
Ok(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read() -> Result<RocketConfig, ConfigError> {
|
pub fn read() -> Result<RocketConfig> {
|
||||||
// Find the config file, starting from the `cwd` and working backwords.
|
// Find the config file, starting from the `cwd` and working backwords.
|
||||||
let file = RocketConfig::find()?;
|
let file = RocketConfig::find()?;
|
||||||
|
|
||||||
|
@ -127,34 +129,39 @@ impl RocketConfig {
|
||||||
RocketConfig::parse(contents, &file.to_string_lossy())
|
RocketConfig::parse(contents, &file.to_string_lossy())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn active_default() -> Result<RocketConfig, ConfigError> {
|
pub fn active_default(filename: &str) -> Result<RocketConfig> {
|
||||||
let mut default = RocketConfig::default();
|
let mut defaults = HashMap::new();
|
||||||
default.active_env = Environment::active()?;
|
defaults.insert(Development, Config::default_for(Development, filename)?);
|
||||||
Ok(default)
|
defaults.insert(Staging, Config::default_for(Staging, filename)?);
|
||||||
|
defaults.insert(Production, Config::default_for(Production, filename)?);
|
||||||
|
|
||||||
|
Ok(RocketConfig {
|
||||||
|
active_env: Environment::active()?,
|
||||||
|
config: defaults,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for RocketConfig {
|
/// Initializes the global RocketConfig by reading the Rocket config file from
|
||||||
fn default() -> RocketConfig {
|
/// the current directory or any of its parents. Returns the active
|
||||||
RocketConfig {
|
/// configuration, which is determined by the config env variable. If there as a
|
||||||
active_env: Environment::Development,
|
/// problem parsing the configuration, the error is printed and the progam is
|
||||||
config: {
|
/// aborted. If there an I/O issue reading the config file, a warning is printed
|
||||||
let mut default_config = HashMap::new();
|
/// and the default configuration is used. If there is no config file, the
|
||||||
default_config.insert(Development, Config::default_for(Development));
|
/// default configuration is used.
|
||||||
default_config.insert(Staging, Config::default_for(Staging));
|
///
|
||||||
default_config.insert(Production, Config::default_for(Production));
|
/// # Panics
|
||||||
default_config
|
///
|
||||||
},
|
/// If there is a problem, prints a nice error message and bails.
|
||||||
}
|
///
|
||||||
|
/// # Thread-Safety
|
||||||
|
///
|
||||||
|
/// This function is _not_ thread-safe. It should be called by a single thread.
|
||||||
|
pub fn init() -> &'static Config {
|
||||||
|
if let Some(config) = active() {
|
||||||
|
return config;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Read the Rocket config file from the current directory or any of its
|
|
||||||
/// parents. If there is no such file, return the default config. A returned
|
|
||||||
/// config will have its active environment set to whatever was passed in with
|
|
||||||
/// the rocket config env variable. If there is a problem doing any of this,
|
|
||||||
/// print a nice error message and bail.
|
|
||||||
pub fn read_or_default() -> RocketConfig {
|
|
||||||
let bail = |e: ConfigError| -> ! {
|
let bail = |e: ConfigError| -> ! {
|
||||||
logger::init(LoggingLevel::Debug);
|
logger::init(LoggingLevel::Debug);
|
||||||
e.pretty_print();
|
e.pretty_print();
|
||||||
|
@ -162,40 +169,54 @@ pub fn read_or_default() -> RocketConfig {
|
||||||
};
|
};
|
||||||
|
|
||||||
use self::ConfigError::*;
|
use self::ConfigError::*;
|
||||||
RocketConfig::read().unwrap_or_else(|e| {
|
let config = RocketConfig::read().unwrap_or_else(|e| {
|
||||||
match e {
|
match e {
|
||||||
ParseError(..) | BadEntry(..) | BadEnv(..) | BadType(..) => bail(e),
|
ParseError(..) | BadEntry(..) | BadEnv(..) | BadType(..)
|
||||||
IOError | BadCWD => warn!("failed reading Rocket.toml. using defaults"),
|
| BadFilePath(..) => bail(e),
|
||||||
|
IOError | BadCWD => warn!("Failed reading Rocket.toml. Using defaults."),
|
||||||
NotFound => { /* try using the default below */ }
|
NotFound => { /* try using the default below */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
RocketConfig::active_default().unwrap_or_else(|e| bail(e))
|
let default_path = match env::current_dir() {
|
||||||
})
|
Ok(path) => path.join(&format!(".{}.{}", "default", CONFIG_FILENAME)),
|
||||||
|
Err(_) => bail(ConfigError::BadCWD)
|
||||||
|
};
|
||||||
|
|
||||||
|
let filename = default_path.to_string_lossy();
|
||||||
|
RocketConfig::active_default(&filename).unwrap_or_else(|e| bail(e))
|
||||||
|
});
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
CONFIG = Some(config);
|
||||||
|
CONFIG.as_ref().unwrap().active()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn active() -> Option<&'static Config> {
|
||||||
|
unsafe { CONFIG.as_ref().map(|c| c.active()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use super::{RocketConfig, CONFIG_FILENAME, ConfigError};
|
use super::{RocketConfig, ConfigError};
|
||||||
use super::environment::CONFIG_ENV;
|
use super::environment::{Environment, CONFIG_ENV};
|
||||||
use super::Environment::*;
|
use super::Environment::*;
|
||||||
use super::config::Config;
|
use super::config::Config;
|
||||||
|
use super::Result;
|
||||||
|
|
||||||
use ::toml::Value;
|
use ::toml::Value;
|
||||||
use ::logger::LoggingLevel;
|
use ::logger::LoggingLevel;
|
||||||
|
|
||||||
|
const TEST_CONFIG_FILENAME: &'static str = "/tmp/testing/Rocket.toml";
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref ENV_LOCK: Mutex<usize> = Mutex::new(0);
|
static ref ENV_LOCK: Mutex<usize> = Mutex::new(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! check_config {
|
macro_rules! check_config {
|
||||||
($rconfig:expr => { $($param:tt)+ }) => (
|
|
||||||
check_config!($rconfig, Config { $($param)+ })
|
|
||||||
);
|
|
||||||
|
|
||||||
($rconfig:expr, $econfig:expr) => (
|
($rconfig:expr, $econfig:expr) => (
|
||||||
match $rconfig {
|
match $rconfig {
|
||||||
Ok(config) => assert_eq!(config.active(), &$econfig),
|
Ok(config) => assert_eq!(config.active(), &$econfig),
|
||||||
|
@ -211,6 +232,14 @@ mod test {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn active_default() -> Result<RocketConfig> {
|
||||||
|
RocketConfig::active_default(TEST_CONFIG_FILENAME)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_config(env: Environment) -> Config {
|
||||||
|
Config::default_for(env, TEST_CONFIG_FILENAME).expect("config")
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_defaults() {
|
fn test_defaults() {
|
||||||
// Take the lock so changing the environment doesn't cause races.
|
// Take the lock so changing the environment doesn't cause races.
|
||||||
|
@ -218,24 +247,24 @@ mod test {
|
||||||
|
|
||||||
// First, without an environment. Should get development defaults.
|
// First, without an environment. Should get development defaults.
|
||||||
env::remove_var(CONFIG_ENV);
|
env::remove_var(CONFIG_ENV);
|
||||||
check_config!(RocketConfig::active_default(), Config::default_for(Development));
|
check_config!(active_default(), default_config(Development));
|
||||||
|
|
||||||
// Now with an explicit dev environment.
|
// Now with an explicit dev environment.
|
||||||
for env in &["development", "dev"] {
|
for env in &["development", "dev"] {
|
||||||
env::set_var(CONFIG_ENV, env);
|
env::set_var(CONFIG_ENV, env);
|
||||||
check_config!(RocketConfig::active_default(), Config::default_for(Development));
|
check_config!(active_default(), default_config(Development));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now staging.
|
// Now staging.
|
||||||
for env in &["stage", "staging"] {
|
for env in &["stage", "staging"] {
|
||||||
env::set_var(CONFIG_ENV, env);
|
env::set_var(CONFIG_ENV, env);
|
||||||
check_config!(RocketConfig::active_default(), Config::default_for(Staging));
|
check_config!(active_default(), default_config(Staging));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, production.
|
// Finally, production.
|
||||||
for env in &["prod", "production"] {
|
for env in &["prod", "production"] {
|
||||||
env::set_var(CONFIG_ENV, env);
|
env::set_var(CONFIG_ENV, env);
|
||||||
check_config!(RocketConfig::active_default(), Config::default_for(Production));
|
check_config!(active_default(), default_config(Production));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,15 +276,16 @@ mod test {
|
||||||
for env in &["", "p", "pr", "pro", "prodo", " prod", "dev ", "!dev!", "🚀 "] {
|
for env in &["", "p", "pr", "pro", "prodo", " prod", "dev ", "!dev!", "🚀 "] {
|
||||||
env::set_var(CONFIG_ENV, env);
|
env::set_var(CONFIG_ENV, env);
|
||||||
let err = ConfigError::BadEnv(env.to_string());
|
let err = ConfigError::BadEnv(env.to_string());
|
||||||
assert!(RocketConfig::active_default().err().map_or(false, |e| e == err));
|
assert!(active_default().err().map_or(false, |e| e == err));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that a bunch of invalid environment names give the right error.
|
// Test that a bunch of invalid environment names give the right error.
|
||||||
env::remove_var(CONFIG_ENV);
|
env::remove_var(CONFIG_ENV);
|
||||||
for env in &["p", "pr", "pro", "prodo", "bad", "meow", "this", "that"] {
|
for env in &["p", "pr", "pro", "prodo", "bad", "meow", "this", "that"] {
|
||||||
let toml_table = format!("[{}]\n", env);
|
let toml_table = format!("[{}]\n", env);
|
||||||
let err = ConfigError::BadEntry(env.to_string(), CONFIG_FILENAME.into());
|
let e_str = env.to_string();
|
||||||
assert!(RocketConfig::parse(toml_table, CONFIG_FILENAME)
|
let err = ConfigError::BadEntry(e_str, TEST_CONFIG_FILENAME.into());
|
||||||
|
assert!(RocketConfig::parse(toml_table, TEST_CONFIG_FILENAME)
|
||||||
.err().map_or(false, |e| e == err));
|
.err().map_or(false, |e| e == err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -276,36 +306,35 @@ mod test {
|
||||||
pi = 3.14
|
pi = 3.14
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
let mut extra: HashMap<String, Value> = HashMap::new();
|
let mut expected = default_config(Development);
|
||||||
extra.insert("template_dir".to_string(), Value::String("mine".into()));
|
expected.address = "1.2.3.4".to_string();
|
||||||
extra.insert("json".to_string(), Value::Boolean(true));
|
expected.port = 7810;
|
||||||
extra.insert("pi".to_string(), Value::Float(3.14));
|
expected.log_level = LoggingLevel::Critical;
|
||||||
|
expected.session_key = Some("01234567890123456789012345678901".to_string());
|
||||||
let expected = Config {
|
expected.set("template_dir", &Value::String("mine".into())).unwrap();
|
||||||
address: "1.2.3.4".to_string(),
|
expected.set("json", &Value::Boolean(true)).unwrap();
|
||||||
port: 7810,
|
expected.set("pi", &Value::Float(3.14)).unwrap();
|
||||||
log_level: LoggingLevel::Critical,
|
|
||||||
session_key: Some("01234567890123456789012345678901".to_string()),
|
|
||||||
extra: extra
|
|
||||||
};
|
|
||||||
|
|
||||||
|
expected.env = Development;
|
||||||
let dev_config = ["[dev]", config_str].join("\n");
|
let dev_config = ["[dev]", config_str].join("\n");
|
||||||
let parsed = RocketConfig::parse(dev_config, CONFIG_FILENAME);
|
let parsed = RocketConfig::parse(dev_config, TEST_CONFIG_FILENAME);
|
||||||
check_config!(Development, parsed, expected);
|
check_config!(Development, parsed, expected);
|
||||||
check_config!(Staging, parsed, Config::default_for(Staging));
|
check_config!(Staging, parsed, default_config(Staging));
|
||||||
check_config!(Production, parsed, Config::default_for(Production));
|
check_config!(Production, parsed, default_config(Production));
|
||||||
|
|
||||||
|
expected.env = Staging;
|
||||||
let stage_config = ["[stage]", config_str].join("\n");
|
let stage_config = ["[stage]", config_str].join("\n");
|
||||||
let parsed = RocketConfig::parse(stage_config, CONFIG_FILENAME);
|
let parsed = RocketConfig::parse(stage_config, TEST_CONFIG_FILENAME);
|
||||||
check_config!(Staging, parsed, expected);
|
check_config!(Staging, parsed, expected);
|
||||||
check_config!(Development, parsed, Config::default_for(Development));
|
check_config!(Development, parsed, default_config(Development));
|
||||||
check_config!(Production, parsed, Config::default_for(Production));
|
check_config!(Production, parsed, default_config(Production));
|
||||||
|
|
||||||
|
expected.env = Production;
|
||||||
let prod_config = ["[prod]", config_str].join("\n");
|
let prod_config = ["[prod]", config_str].join("\n");
|
||||||
let parsed = RocketConfig::parse(prod_config, CONFIG_FILENAME);
|
let parsed = RocketConfig::parse(prod_config, TEST_CONFIG_FILENAME);
|
||||||
check_config!(Production, parsed, expected);
|
check_config!(Production, parsed, expected);
|
||||||
check_config!(Development, parsed, Config::default_for(Development));
|
check_config!(Development, parsed, default_config(Development));
|
||||||
check_config!(Staging, parsed, Config::default_for(Staging));
|
check_config!(Staging, parsed, default_config(Staging));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -317,29 +346,25 @@ mod test {
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(RocketConfig::parse(r#"
|
||||||
[development]
|
[development]
|
||||||
address = "localhost"
|
address = "localhost"
|
||||||
"#.to_string(), CONFIG_FILENAME) => {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
address: "localhost".to_string(),
|
default_config(Development).address("localhost".into())
|
||||||
..Config::default_for(Development)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(RocketConfig::parse(r#"
|
||||||
[dev]
|
[dev]
|
||||||
address = "127.0.0.1"
|
address = "127.0.0.1"
|
||||||
"#.to_string(), CONFIG_FILENAME) => {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
address: "127.0.0.1".to_string(),
|
default_config(Development).address("127.0.0.1".into())
|
||||||
..Config::default_for(Development)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(RocketConfig::parse(r#"
|
||||||
[dev]
|
[dev]
|
||||||
address = "0.0.0.0"
|
address = "0.0.0.0"
|
||||||
"#.to_string(), CONFIG_FILENAME) => {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
address: "0.0.0.0".to_string(),
|
default_config(Development).address("0.0.0.0".into())
|
||||||
..Config::default_for(Development)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_bad_address_values() {
|
fn test_bad_address_values() {
|
||||||
// Take the lock so changing the environment doesn't cause races.
|
// Take the lock so changing the environment doesn't cause races.
|
||||||
|
@ -349,27 +374,27 @@ mod test {
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(RocketConfig::parse(r#"
|
||||||
[development]
|
[development]
|
||||||
address = 0000
|
address = 0000
|
||||||
"#.to_string(), CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(RocketConfig::parse(r#"
|
||||||
[development]
|
[development]
|
||||||
address = true
|
address = true
|
||||||
"#.to_string(), CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(RocketConfig::parse(r#"
|
||||||
[development]
|
[development]
|
||||||
address = "_idk_"
|
address = "_idk_"
|
||||||
"#.to_string(), CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(RocketConfig::parse(r#"
|
||||||
[staging]
|
[staging]
|
||||||
address = "1.2.3.4:100"
|
address = "1.2.3.4:100"
|
||||||
"#.to_string(), CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(RocketConfig::parse(r#"
|
||||||
[production]
|
[production]
|
||||||
address = "1.2.3.4.5.6"
|
address = "1.2.3.4.5.6"
|
||||||
"#.to_string(), CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -381,17 +406,15 @@ mod test {
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(RocketConfig::parse(r#"
|
||||||
[stage]
|
[stage]
|
||||||
port = 100
|
port = 100
|
||||||
"#.to_string(), CONFIG_FILENAME) => {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
port: 100,
|
default_config(Staging).port(100)
|
||||||
..Config::default_for(Staging)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(RocketConfig::parse(r#"
|
||||||
[stage]
|
[stage]
|
||||||
port = 6000
|
port = 6000
|
||||||
"#.to_string(), CONFIG_FILENAME) => {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
port: 6000,
|
default_config(Staging).port(6000)
|
||||||
..Config::default_for(Staging)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -404,17 +427,17 @@ mod test {
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(RocketConfig::parse(r#"
|
||||||
[development]
|
[development]
|
||||||
port = true
|
port = true
|
||||||
"#.to_string(), CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(RocketConfig::parse(r#"
|
||||||
[production]
|
[production]
|
||||||
port = "hello"
|
port = "hello"
|
||||||
"#.to_string(), CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(RocketConfig::parse(r#"
|
||||||
[staging]
|
[staging]
|
||||||
port = -1
|
port = -1
|
||||||
"#.to_string(), CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -426,26 +449,23 @@ mod test {
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(RocketConfig::parse(r#"
|
||||||
[stage]
|
[stage]
|
||||||
log = "normal"
|
log = "normal"
|
||||||
"#.to_string(), CONFIG_FILENAME) => {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
log_level: LoggingLevel::Normal,
|
default_config(Staging).log_level(LoggingLevel::Normal)
|
||||||
..Config::default_for(Staging)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(RocketConfig::parse(r#"
|
||||||
[stage]
|
[stage]
|
||||||
log = "debug"
|
log = "debug"
|
||||||
"#.to_string(), CONFIG_FILENAME) => {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
log_level: LoggingLevel::Debug,
|
default_config(Staging).log_level(LoggingLevel::Debug)
|
||||||
..Config::default_for(Staging)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(RocketConfig::parse(r#"
|
||||||
[stage]
|
[stage]
|
||||||
log = "critical"
|
log = "critical"
|
||||||
"#.to_string(), CONFIG_FILENAME) => {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
log_level: LoggingLevel::Critical,
|
default_config(Staging).log_level(LoggingLevel::Critical)
|
||||||
..Config::default_for(Staging)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,17 +478,17 @@ mod test {
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(RocketConfig::parse(r#"
|
||||||
[dev]
|
[dev]
|
||||||
log = false
|
log = false
|
||||||
"#.to_string(), CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(RocketConfig::parse(r#"
|
||||||
[development]
|
[development]
|
||||||
log = 0
|
log = 0
|
||||||
"#.to_string(), CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(RocketConfig::parse(r#"
|
||||||
[prod]
|
[prod]
|
||||||
log = "no"
|
log = "no"
|
||||||
"#.to_string(), CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -480,17 +500,19 @@ mod test {
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(RocketConfig::parse(r#"
|
||||||
[stage]
|
[stage]
|
||||||
session_key = "VheMwXIBygSmOlZAhuWl2B+zgvTN3WW5"
|
session_key = "VheMwXIBygSmOlZAhuWl2B+zgvTN3WW5"
|
||||||
"#.to_string(), CONFIG_FILENAME) => {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
session_key: Some("VheMwXIBygSmOlZAhuWl2B+zgvTN3WW5".into()),
|
default_config(Staging).session_key(
|
||||||
..Config::default_for(Staging)
|
"VheMwXIBygSmOlZAhuWl2B+zgvTN3WW5".into()
|
||||||
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
check_config!(RocketConfig::parse(r#"
|
check_config!(RocketConfig::parse(r#"
|
||||||
[stage]
|
[stage]
|
||||||
session_key = "adL5fFIPmZBrlyHk2YT4NLV3YCk2gFXz"
|
session_key = "adL5fFIPmZBrlyHk2YT4NLV3YCk2gFXz"
|
||||||
"#.to_string(), CONFIG_FILENAME) => {
|
"#.to_string(), TEST_CONFIG_FILENAME), {
|
||||||
session_key: Some("adL5fFIPmZBrlyHk2YT4NLV3YCk2gFXz".into()),
|
default_config(Staging).session_key(
|
||||||
..Config::default_for(Staging)
|
"adL5fFIPmZBrlyHk2YT4NLV3YCk2gFXz".into()
|
||||||
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -503,17 +525,17 @@ mod test {
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(RocketConfig::parse(r#"
|
||||||
[dev]
|
[dev]
|
||||||
session_key = true
|
session_key = true
|
||||||
"#.to_string(), CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(RocketConfig::parse(r#"
|
||||||
[dev]
|
[dev]
|
||||||
session_key = 1283724897238945234897
|
session_key = 1283724897238945234897
|
||||||
"#.to_string(), CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(RocketConfig::parse(r#"
|
||||||
[dev]
|
[dev]
|
||||||
session_key = "abcv"
|
session_key = "abcv"
|
||||||
"#.to_string(), CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -524,16 +546,16 @@ mod test {
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(RocketConfig::parse(r#"
|
||||||
[dev
|
[dev
|
||||||
"#.to_string(), CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(RocketConfig::parse(r#"
|
||||||
[dev]
|
[dev]
|
||||||
1.2.3 = 2
|
1.2.3 = 2
|
||||||
"#.to_string(), CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
|
|
||||||
assert!(RocketConfig::parse(r#"
|
assert!(RocketConfig::parse(r#"
|
||||||
[dev]
|
[dev]
|
||||||
session_key = "abcv" = other
|
session_key = "abcv" = other
|
||||||
"#.to_string(), CONFIG_FILENAME).is_err());
|
"#.to_string(), TEST_CONFIG_FILENAME).is_err());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#![feature(question_mark)]
|
#![feature(question_mark)]
|
||||||
#![feature(specialization)]
|
#![feature(specialization)]
|
||||||
#![feature(conservative_impl_trait)]
|
#![feature(conservative_impl_trait)]
|
||||||
|
#![feature(drop_types_in_const)]
|
||||||
|
|
||||||
//! # Rocket - Core API Documentation
|
//! # Rocket - Core API Documentation
|
||||||
//!
|
//!
|
||||||
|
@ -73,13 +74,13 @@ pub mod http;
|
||||||
pub mod request;
|
pub mod request;
|
||||||
pub mod response;
|
pub mod response;
|
||||||
pub mod outcome;
|
pub mod outcome;
|
||||||
|
pub mod config;
|
||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
mod router;
|
mod router;
|
||||||
mod rocket;
|
mod rocket;
|
||||||
mod codegen;
|
mod codegen;
|
||||||
mod catcher;
|
mod catcher;
|
||||||
mod config;
|
|
||||||
|
|
||||||
/// Defines the types for request and error handlers.
|
/// Defines the types for request and error handlers.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
|
|
@ -154,7 +154,7 @@ impl Rocket {
|
||||||
if !responder.respond(response).is_success() {
|
if !responder.respond(response).is_success() {
|
||||||
error_!("Catcher outcome was unsuccessul; aborting response.");
|
error_!("Catcher outcome was unsuccessul; aborting response.");
|
||||||
} else {
|
} else {
|
||||||
info_!("Responded with catcher.");
|
info_!("Responded with {} catcher.", White.paint(code));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error_!("Catcher returned an incomplete response.");
|
error_!("Catcher returned an incomplete response.");
|
||||||
|
@ -226,21 +226,23 @@ impl Rocket {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ignite() -> Rocket {
|
pub fn ignite() -> Rocket {
|
||||||
// Note: read_or_default will exit the process under errors.
|
// Note: init() will exit the process under config errors.
|
||||||
let config = config::read_or_default();
|
let config = config::init();
|
||||||
|
|
||||||
logger::init(config.active().log_level);
|
logger::init(config.log_level);
|
||||||
info!("🔧 Configured for {}.", config.active_env);
|
info!("🔧 Configured for {}.", config.env);
|
||||||
info_!("listening: {}:{}",
|
info_!("listening: {}:{}",
|
||||||
White.paint(&config.active().address),
|
White.paint(&config.address),
|
||||||
White.paint(&config.active().port));
|
White.paint(&config.port));
|
||||||
info_!("logging: {:?}", White.paint(config.active().log_level));
|
info_!("logging: {:?}", White.paint(config.log_level));
|
||||||
info_!("session key: {}",
|
info_!("session key: {}", White.paint(config.session_key.is_some()));
|
||||||
White.paint(config.active().session_key.is_some()));
|
for (name, value) in config.extras() {
|
||||||
|
info_!("{} {}: {}", Yellow.paint("[extra]"), name, White.paint(value));
|
||||||
|
}
|
||||||
|
|
||||||
Rocket {
|
Rocket {
|
||||||
address: config.active().address.clone(),
|
address: config.address.clone(),
|
||||||
port: config.active().port,
|
port: config.port,
|
||||||
router: Router::new(),
|
router: Router::new(),
|
||||||
default_catchers: catcher::defaults::get(),
|
default_catchers: catcher::defaults::get(),
|
||||||
catchers: catcher::defaults::get(),
|
catchers: catcher::defaults::get(),
|
||||||
|
|
Loading…
Reference in New Issue