Compare commits
2 Commits
739b3ad0c5
...
0768507036
Author | SHA1 | Date |
---|---|---|
meeg_leeto | 0768507036 | |
meeg_leeto | a3fc446dbc |
|
@ -838,7 +838,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "lonk"
|
||||
version = "1.0.1"
|
||||
version = "2.0.1"
|
||||
dependencies = [
|
||||
"argh",
|
||||
"async-object-pool",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "lonk"
|
||||
version = "1.0.1"
|
||||
version = "2.0.1"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"version": 1,
|
||||
"version": 2,
|
||||
"db": {
|
||||
"address": "redis://redis:6379",
|
||||
"expire_seconds": 259200
|
||||
|
@ -10,7 +10,8 @@
|
|||
},
|
||||
"log_rules": {
|
||||
"error_log_file": "/data/log/error.log",
|
||||
"access_log_file": "/data/log/access.log"
|
||||
"access_log_file": "/data/log/access.log",
|
||||
"link_log_file": "/data/log/link.log"
|
||||
},
|
||||
"serve_rules": {
|
||||
"dir": {
|
||||
|
|
65
src/main.rs
65
src/main.rs
|
@ -142,8 +142,10 @@ mod conf {
|
|||
pub struct LogRules {
|
||||
/// Where to write error logs to. The file will be appended to.
|
||||
pub error_log_file: PathBuf,
|
||||
/// Where to write access ogs to. The file will be appended to.
|
||||
/// Where to write access logs to. The file will be appended to.
|
||||
pub access_log_file: PathBuf,
|
||||
/// Where to write link shortening logs to. The file will be appended to.
|
||||
pub link_log_file: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||
|
@ -183,6 +185,7 @@ mod conf {
|
|||
ServeDirNotExists(PathBuf),
|
||||
AccessLogDirectoryNotExists(PathBuf),
|
||||
ErrorLogDirectoryNotExists(PathBuf),
|
||||
LinkLogDirectoryNotExists(PathBuf),
|
||||
}
|
||||
|
||||
impl Config {
|
||||
|
@ -223,24 +226,27 @@ mod conf {
|
|||
}
|
||||
|
||||
// Check access and error log parent directories
|
||||
fn check_exists<E>(path: &PathBuf, to_err: impl FnOnce(PathBuf) -> E) -> Result<(), E> {
|
||||
let weak_canonical = normalize_path(path);
|
||||
if let Some(parent) = weak_canonical.parent() {
|
||||
if !parent.exists() {
|
||||
return Err(to_err(parent.to_path_buf()));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
// - Access log file
|
||||
let weak_canonical = normalize_path(&self.log_rules.access_log_file);
|
||||
if let Some(parent) = weak_canonical.parent() {
|
||||
if !parent.exists() {
|
||||
return Err(ConfigParseError::AccessLogDirectoryNotExists(
|
||||
parent.to_path_buf(),
|
||||
));
|
||||
}
|
||||
}
|
||||
check_exists(&self.log_rules.access_log_file, |path| {
|
||||
ConfigParseError::AccessLogDirectoryNotExists(path)
|
||||
})?;
|
||||
// - Error log file
|
||||
let weak_canonical = normalize_path(&self.log_rules.error_log_file);
|
||||
if let Some(parent) = weak_canonical.parent() {
|
||||
if !parent.exists() {
|
||||
return Err(ConfigParseError::ErrorLogDirectoryNotExists(
|
||||
parent.to_path_buf(),
|
||||
));
|
||||
}
|
||||
}
|
||||
check_exists(&self.log_rules.error_log_file, |path| {
|
||||
ConfigParseError::ErrorLogDirectoryNotExists(path)
|
||||
})?;
|
||||
// - Link log file
|
||||
check_exists(&self.log_rules.link_log_file, |path| {
|
||||
ConfigParseError::LinkLogDirectoryNotExists(path)
|
||||
})?;
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
|
@ -308,8 +314,8 @@ mod conf {
|
|||
eprintln!(
|
||||
concat!("Configuration file has outdated version.\n",
|
||||
"Expected version field to be {} but got {}."),
|
||||
config_version(),
|
||||
old_version,
|
||||
config_version()
|
||||
);
|
||||
}
|
||||
ConfigParseError::ServeDirNotExists(dir) => {
|
||||
|
@ -342,6 +348,9 @@ mod conf {
|
|||
ConfigParseError::ErrorLogDirectoryNotExists(dir) => {
|
||||
eprintln!("Error log file should have parent directory {}, but this directory does not exist.", dir.to_string_lossy())
|
||||
}
|
||||
ConfigParseError::LinkLogDirectoryNotExists(dir) => {
|
||||
eprintln!("Link registration log file should have parent directory {}, but this directory does not exist.", dir.to_string_lossy())
|
||||
}
|
||||
}
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
@ -406,6 +415,7 @@ mod conf {
|
|||
Self {
|
||||
error_log_file: "/etc/lonk/log/error.log".into(),
|
||||
access_log_file: "/etc/lonk/log/access.log".into(),
|
||||
link_log_file: "/etc/lonk/log/links.log".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -924,6 +934,7 @@ mod service {
|
|||
pub struct Logger {
|
||||
access_tx: sync::mpsc::UnboundedSender<String>,
|
||||
error_tx: sync::mpsc::UnboundedSender<String>,
|
||||
link_tx: sync::mpsc::UnboundedSender<String>,
|
||||
}
|
||||
|
||||
impl Logger {
|
||||
|
@ -931,6 +942,7 @@ mod service {
|
|||
// Create the communication channels
|
||||
let (access_tx, access_rx) = sync::mpsc::unbounded_channel::<String>();
|
||||
let (error_tx, error_rx) = sync::mpsc::unbounded_channel::<String>();
|
||||
let (link_tx, link_rx) = sync::mpsc::unbounded_channel::<String>();
|
||||
|
||||
// Start the logging tasks
|
||||
tokio::spawn(Self::logging_task(
|
||||
|
@ -938,11 +950,13 @@ mod service {
|
|||
config.access_log_file.clone(),
|
||||
));
|
||||
tokio::spawn(Self::logging_task(error_rx, config.error_log_file.clone()));
|
||||
tokio::spawn(Self::logging_task(link_rx, config.link_log_file.clone()));
|
||||
|
||||
// Done
|
||||
Logger {
|
||||
access_tx,
|
||||
error_tx,
|
||||
link_tx,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -965,6 +979,16 @@ mod service {
|
|||
pub fn error(&self, msg: String) -> Result<(), ()> {
|
||||
self.error_tx.send(msg).map_err(|_| ())
|
||||
}
|
||||
|
||||
/// Log a message into the link log file.
|
||||
///
|
||||
/// Returns a Result with empty type; if posting the log message
|
||||
/// failed for any reason, it's unlikely to recover, and the user
|
||||
/// should decide either to stop logging, ignore these errors, or
|
||||
/// halt the program.
|
||||
pub fn link(&self, msg: String) -> Result<(), ()> {
|
||||
self.link_tx.send(msg).map_err(|_| ())
|
||||
}
|
||||
|
||||
/// The task responsible for receiving the log messages and actually
|
||||
/// writing them into the corresponding files. One task is created
|
||||
|
@ -1068,7 +1092,7 @@ async fn shorten(
|
|||
Ok(result) => match result {
|
||||
service::db::AddResult::Success(slug) => {
|
||||
logger
|
||||
.access(format!("{} -> {}\n", slug.inner_str(), url))
|
||||
.link(format!("{} -> {}\n", slug.inner_str(), url))
|
||||
.ok();
|
||||
Ok(slug)
|
||||
}
|
||||
|
@ -1237,8 +1261,7 @@ async fn serve() {
|
|||
// GET /
|
||||
// This should be the last thing matched, so that anything that doesn't
|
||||
// match another filter will try to match a file.
|
||||
let homepage = warp::get()
|
||||
.and(config.serve_rules.dir.to_filter());
|
||||
let homepage = warp::get().and(config.serve_rules.dir.to_filter());
|
||||
|
||||
let get_routes = warp::get().and(link.or(homepage));
|
||||
let post_routes = warp::post().and(shorten);
|
||||
|
|
Loading…
Reference in New Issue