mirror of https://github.com/mastodon/flodgatt
Store error messages as data
This commit is contained in:
parent
74a2ac3bb2
commit
503ddfd510
|
@ -1,7 +1,7 @@
|
|||
use crate::{config::deployment_cfg_types::*, err::FromStrOrDie, maybe_update};
|
||||
use crate::config::deployment_cfg_types::*;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct DeploymentConfig<'a> {
|
||||
pub env: Env,
|
||||
pub log_level: LogLevel,
|
||||
|
@ -12,29 +12,12 @@ pub struct DeploymentConfig<'a> {
|
|||
pub sse_interval: SseInterval,
|
||||
pub ws_interval: WsInterval,
|
||||
}
|
||||
impl Default for DeploymentConfig<'_> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
env: Env::Development,
|
||||
log_level: LogLevel::default(),
|
||||
address: FlodgattAddr::default(),
|
||||
port: Port2::default(),
|
||||
unix_socket: Socket::default(),
|
||||
cors: Cors {
|
||||
allowed_methods: vec!["GET", "OPTIONS"],
|
||||
allowed_headers: vec!["Authorization", "Accept", "Cache-Control"],
|
||||
},
|
||||
sse_interval: SseInterval::default(),
|
||||
ws_interval: WsInterval::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DeploymentConfig<'_> {
|
||||
pub fn from_env(env_vars: HashMap<String, String>) -> Self {
|
||||
let mut res = Self::default()
|
||||
.maybe_update_env(env_vars.get("NODE_ENV").map(Env::from_str_or_die))
|
||||
.maybe_update_env(env_vars.get("RUST_ENV").map(Env::from_str_or_die));
|
||||
|
||||
let mut res = Self::default();
|
||||
res.env = Env::from_env_var_or_die(env_vars.get("NODE_ENV"));
|
||||
res.env = Env::from_env_var_or_die(env_vars.get("RUST_ENV"));
|
||||
res.log_level = LogLevel::from_env_var_or_die(env_vars.get("RUST_LOG"));
|
||||
res.address = FlodgattAddr::from_env_var_or_die(env_vars.get("BIND"));
|
||||
res.port = Port2::from_env_var_or_die(env_vars.get("PORT"));
|
||||
|
@ -45,14 +28,6 @@ impl DeploymentConfig<'_> {
|
|||
res.log()
|
||||
}
|
||||
|
||||
maybe_update!(maybe_update_env; env: Env);
|
||||
// maybe_update!(maybe_update_port; port: Port);
|
||||
maybe_update!(maybe_update_address; address: FlodgattAddr);
|
||||
// maybe_update!(maybe_update_unix_socket; Some(unix_socket: Socket));
|
||||
// maybe_update!(maybe_update_log_level; log_level: LogLevel);
|
||||
// maybe_update!(maybe_update_sse_int; sse_interval: SseInterval);
|
||||
// maybe_update!(maybe_update_ws_int; ws_interval: WsInterval);
|
||||
|
||||
fn log(self) -> Self {
|
||||
log::warn!("Using deployment configuration:\n {:#?}", &self);
|
||||
self
|
||||
|
|
|
@ -1,28 +1,36 @@
|
|||
use crate::{derive_from_str_or_die, err::FromStrOrDie, from_env_var};
|
||||
use crate::from_env_var;
|
||||
use std::{fmt, net::IpAddr, os::unix::net::UnixListener, str::FromStr, time::Duration};
|
||||
use strum_macros::{EnumString, EnumVariantNames};
|
||||
|
||||
/// The current environment, which controls what file to read other ENV vars from
|
||||
from_env_var!(/// The current environment, which controls what file to read other ENV vars from
|
||||
Env {
|
||||
inner: EnvInner::Development; EnvInner,
|
||||
env_var: "RUST_ENV",
|
||||
allowed_values: format!("one of: {:?}", EnvInner::variants()),
|
||||
}
|
||||
inner_from_str(|s| EnvInner::from_str(s).ok())
|
||||
);
|
||||
#[derive(EnumString, EnumVariantNames, Debug)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum Env {
|
||||
pub enum EnvInner {
|
||||
Production,
|
||||
Development,
|
||||
}
|
||||
derive_from_str_or_die!(Env {
|
||||
name: "RUST_ENV",
|
||||
value: format!("one of: {:?}", Self::variants())
|
||||
});
|
||||
|
||||
// The address to run Flodgatt on
|
||||
from_env_var!(FlodgattAddr {
|
||||
inner: IpAddr::V4("127.0.0.1".parse().expect("hardcoded")); IpAddr,
|
||||
env_var: "BIND",
|
||||
allowed_values: "a valid address (e.g., 127.0.0.1)".to_string(),
|
||||
}
|
||||
inner_from_str(|s| s.parse().ok()));
|
||||
|
||||
/// How verbosely Flodgatt should log messages
|
||||
from_env_var!(/// The address to run Flodgatt on
|
||||
FlodgattAddr {
|
||||
inner: IpAddr::V4("127.0.0.1".parse().expect("hardcoded")); IpAddr,
|
||||
env_var: "BIND",
|
||||
allowed_values: "a valid address (e.g., 127.0.0.1)".to_string(),
|
||||
}
|
||||
inner_from_str(|s| s.parse().ok()));
|
||||
from_env_var!(/// How verbosely Flodgatt should log messages
|
||||
LogLevel {
|
||||
inner: LogLevelInner::Warn; LogLevelInner,
|
||||
env_var: "RUST_LOG",
|
||||
allowed_values: format!("one of {:?}", LogLevelInner::variants()),
|
||||
}
|
||||
inner_from_str(|s| LogLevelInner::from_str(s).ok()));
|
||||
#[derive(EnumString, EnumVariantNames, Debug)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum LogLevelInner {
|
||||
|
@ -32,47 +40,37 @@ pub enum LogLevelInner {
|
|||
Warn,
|
||||
Error,
|
||||
}
|
||||
from_env_var!(LogLevel {
|
||||
inner: LogLevelInner::Warn; LogLevelInner,
|
||||
env_var: "RUST_LOG",
|
||||
allowed_values: format!("one of {:?}", LogLevelInner::variants()),
|
||||
}
|
||||
inner_from_str(|s| LogLevelInner::from_str(s).ok()));
|
||||
|
||||
// A Unix Socket to use in place of a local address
|
||||
from_env_var!(Socket{
|
||||
inner: None; Option<UnixListener>,
|
||||
env_var: "SOCKET",
|
||||
allowed_values: "a valid Unix Socket".to_string(),
|
||||
}
|
||||
inner_from_str(|s| match UnixListener::bind(s).ok() {
|
||||
Some(socket) => Some(Some(socket)),
|
||||
None => None,
|
||||
}));
|
||||
|
||||
// The time between replies sent via WebSocket
|
||||
from_env_var!(WsInterval {
|
||||
inner: Duration::from_millis(100); Duration,
|
||||
env_var: "WS_FREQ",
|
||||
allowed_values: "a number of milliseconds".to_string(),
|
||||
}
|
||||
inner_from_str(|s| s.parse().map(|num| Duration::from_millis(num)).ok()));
|
||||
|
||||
// The time between replies sent via Server Sent Events
|
||||
from_env_var!(SseInterval {
|
||||
inner: Duration::from_millis(100); Duration,
|
||||
env_var: "SSE_FREQ",
|
||||
allowed_values: "a number of milliseconds".to_string(),
|
||||
}
|
||||
inner_from_str(|s| s.parse().map(|num| Duration::from_millis(num)).ok()));
|
||||
|
||||
// The port to run Flodgatt on
|
||||
from_env_var!(Port2 {
|
||||
inner: 4000; u16,
|
||||
env_var: "PORT",
|
||||
allowed_values: "a number".to_string(),
|
||||
}
|
||||
inner_from_str(|s| s.parse().ok()));
|
||||
from_env_var!(/// A Unix Socket to use in place of a local address
|
||||
Socket{
|
||||
inner: None; Option<UnixListener>,
|
||||
env_var: "SOCKET",
|
||||
allowed_values: "a valid Unix Socket".to_string(),
|
||||
}
|
||||
inner_from_str(|s| match UnixListener::bind(s).ok() {
|
||||
Some(socket) => Some(Some(socket)),
|
||||
None => None,
|
||||
}));
|
||||
from_env_var!(/// The time between replies sent via WebSocket
|
||||
WsInterval {
|
||||
inner: Duration::from_millis(100); Duration,
|
||||
env_var: "WS_FREQ",
|
||||
allowed_values: "a number of milliseconds".to_string(),
|
||||
}
|
||||
inner_from_str(|s| s.parse().map(|num| Duration::from_millis(num)).ok()));
|
||||
from_env_var!(/// The time between replies sent via Server Sent Events
|
||||
SseInterval {
|
||||
inner: Duration::from_millis(100); Duration,
|
||||
env_var: "SSE_FREQ",
|
||||
allowed_values: "a number of milliseconds".to_string(),
|
||||
}
|
||||
inner_from_str(|s| s.parse().map(|num| Duration::from_millis(num)).ok()));
|
||||
from_env_var!(/// The port to run Flodgatt on
|
||||
Port2 {
|
||||
inner: 4000; u16,
|
||||
env_var: "PORT",
|
||||
allowed_values: "a number".to_string(),
|
||||
}
|
||||
inner_from_str(|s| s.parse().ok()));
|
||||
|
||||
/// Permissions for Cross Origin Resource Sharing (CORS)
|
||||
pub struct Cors<'a> {
|
||||
|
@ -88,3 +86,11 @@ impl fmt::Debug for Cors<'_> {
|
|||
)
|
||||
}
|
||||
}
|
||||
impl std::default::Default for Cors<'_> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
allowed_methods: vec!["GET", "OPTIONS"],
|
||||
allowed_headers: vec!["Authorization", "Accept", "Cache-Control"],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,42 +22,10 @@ macro_rules! maybe_update {
|
|||
None => Self { ..self }
|
||||
}
|
||||
})}
|
||||
#[macro_export]
|
||||
macro_rules! derive_deref {
|
||||
($name:ident: $type:ty) => {
|
||||
impl std::ops::Deref for $name {
|
||||
type Target = $type;
|
||||
fn deref(&self) -> &$type {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
macro_rules! derive_oneline_debug {
|
||||
($item:ident) => {
|
||||
impl std::fmt::Debug for $item {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self.0)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
#[macro_export]
|
||||
macro_rules! derive_from_str_or_die {
|
||||
($item:ident {name: $name:expr,
|
||||
value: $value:expr}) => {
|
||||
impl FromStrOrDie<Self> for $item {
|
||||
fn name_and_values() -> (&'static str, String) {
|
||||
($name, $value)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! from_env_var {
|
||||
($name:ident {
|
||||
($(#[$outer:meta])*
|
||||
$name:ident {
|
||||
inner: $inner:expr; $type:ty,
|
||||
env_var: $env_var:tt,
|
||||
allowed_values: $allowed_values:expr,
|
||||
|
@ -80,6 +48,15 @@ macro_rules! from_env_var {
|
|||
&self.inner
|
||||
}
|
||||
}
|
||||
impl std::default::Default for $name {
|
||||
fn default() -> Self {
|
||||
$name {
|
||||
inner: $inner,
|
||||
env_var: $env_var.to_string(),
|
||||
allowed_values: $allowed_values,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl $name {
|
||||
fn inner_from_str($arg: &str) -> Option<$type> {
|
||||
$body
|
||||
|
@ -88,13 +65,6 @@ macro_rules! from_env_var {
|
|||
self.inner = inner;
|
||||
self
|
||||
}
|
||||
pub fn default() -> Self {
|
||||
$name {
|
||||
inner: $inner,
|
||||
env_var: $env_var.to_string(),
|
||||
allowed_values: $allowed_values,
|
||||
}
|
||||
}
|
||||
pub fn from_env_var_or_die(env: Option<&String>) -> Self {
|
||||
let mut res = Self::default();
|
||||
if let Some(value) = env {
|
||||
|
|
16
src/err.rs
16
src/err.rs
|
@ -1,21 +1,5 @@
|
|||
use serde_derive::Serialize;
|
||||
use std::fmt::Display;
|
||||
use std::str::FromStr;
|
||||
|
||||
pub trait FromStrOrDie<T: FromStr> {
|
||||
fn name_and_values() -> (&'static str, String);
|
||||
fn from_str_or_die(s: &String) -> T {
|
||||
T::from_str(s).unwrap_or_else(|_| {
|
||||
die_with_msg(&format!(
|
||||
"\"{}\" is an invalid value for {}\n {} must be {}",
|
||||
s,
|
||||
Self::name_and_values().0,
|
||||
Self::name_and_values().0,
|
||||
Self::name_and_values().1,
|
||||
))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn die_with_msg(msg: impl Display) -> ! {
|
||||
eprintln!("FATAL ERROR: {}", msg);
|
||||
|
|
Loading…
Reference in New Issue