mirror of
https://github.com/YGGverse/nexy.git
synced 2026-03-31 09:15:28 +00:00
reorganize debug events
This commit is contained in:
parent
57dfe79568
commit
212ffeab79
10 changed files with 75 additions and 117 deletions
|
|
@ -41,12 +41,8 @@ nexy -p /path/to/public_dir
|
||||||
|
|
||||||
[default: 127.0.0.1:1900 [::1]:1900]
|
[default: 127.0.0.1:1900 [::1]:1900]
|
||||||
|
|
||||||
-d, --debug <DEBUG>
|
-d, --debug
|
||||||
Debug level
|
Print debug information
|
||||||
|
|
||||||
* `e` - error * `i` - info
|
|
||||||
|
|
||||||
[default: ei]
|
|
||||||
|
|
||||||
-p, --public <PUBLIC>
|
-p, --public <PUBLIC>
|
||||||
Absolute path to the public files directory
|
Absolute path to the public files directory
|
||||||
|
|
|
||||||
|
|
@ -20,12 +20,9 @@ pub struct Config {
|
||||||
])]
|
])]
|
||||||
pub bind: Vec<String>,
|
pub bind: Vec<String>,
|
||||||
|
|
||||||
/// Debug level
|
/// Print debug information
|
||||||
///
|
#[arg(short, long, default_value_t = false)]
|
||||||
/// * `e` - error
|
pub debug: bool,
|
||||||
/// * `i` - info
|
|
||||||
#[arg(short, long, default_value_t = String::from("ei"))]
|
|
||||||
pub debug: String,
|
|
||||||
|
|
||||||
/// Absolute path to the public files directory
|
/// Absolute path to the public files directory
|
||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
|
|
|
||||||
12
src/main.rs
12
src/main.rs
|
|
@ -5,10 +5,10 @@ mod session;
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
fn main() -> anyhow::Result<()> {
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
let a = config::Config::parse();
|
let c = config::Config::parse();
|
||||||
let s = std::sync::Arc::new(session::Session::init(&a)?);
|
let s = std::sync::Arc::new(session::Session::init(&c)?);
|
||||||
for b in a.bind {
|
for b in c.bind {
|
||||||
s.debug.info(&format!("start server on `{b}`..."));
|
println!("start server on `{b}`...");
|
||||||
match std::net::TcpListener::bind(&b) {
|
match std::net::TcpListener::bind(&b) {
|
||||||
Ok(r) => {
|
Ok(r) => {
|
||||||
std::thread::spawn({
|
std::thread::spawn({
|
||||||
|
|
@ -16,9 +16,7 @@ fn main() -> anyhow::Result<()> {
|
||||||
move || server::start(r, &s)
|
move || server::start(r, &s)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Err(e) => s
|
Err(e) => eprintln!("failed to start server on `{b}`: `{e}`"),
|
||||||
.debug
|
|
||||||
.error(&format!("failed to start server on `{b}`: `{e}`")),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::thread::park();
|
std::thread::park();
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
/// Internal types
|
/// Internal server response types
|
||||||
pub enum Response<'a> {
|
pub enum Response<'a> {
|
||||||
/// Includes reference to the original request
|
/// Includes reference to the original request
|
||||||
AccessDenied(&'a str),
|
AccessDenied(&'a str),
|
||||||
/// Includes server-side error description
|
/// Includes query + server-side error description
|
||||||
InternalServerError(String),
|
InternalServerError(&'a str, String),
|
||||||
/// Includes reference to the original request
|
/// Includes reference to the original request
|
||||||
NotFound(&'a str),
|
NotFound(&'a str),
|
||||||
/// Includes bytes array
|
/// Includes bytes array
|
||||||
|
|
|
||||||
|
|
@ -12,15 +12,11 @@ pub fn start(server: TcpListener, session: &Arc<Session>) {
|
||||||
let session = session.clone();
|
let session = session.clone();
|
||||||
move || match Connection::init(&session, stream) {
|
move || match Connection::init(&session, stream) {
|
||||||
Ok(connection) => connection.handle(),
|
Ok(connection) => connection.handle(),
|
||||||
Err(e) => session
|
Err(e) => eprintln!("failed to init connection: `{e}`"),
|
||||||
.debug
|
|
||||||
.error(&format!("failed to init connection: `{e}`")),
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Err(e) => session
|
Err(e) => eprintln!("failed to accept incoming connection: `{e}`"),
|
||||||
.debug
|
|
||||||
.error(&format!("failed to accept incoming connection: `{e}`")),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,10 +35,12 @@ impl Connection {
|
||||||
let mut t = 0; // total bytes
|
let mut t = 0; // total bytes
|
||||||
match self.request() {
|
match self.request() {
|
||||||
Ok(q) => {
|
Ok(q) => {
|
||||||
self.session.debug.info(&format!(
|
if self.session.is_debug {
|
||||||
"[{}] < [{}] request `{q}`...",
|
println!(
|
||||||
self.address.server, self.address.client
|
"[{}] < [{}] request `{q}`...",
|
||||||
));
|
self.address.server, self.address.client
|
||||||
|
)
|
||||||
|
}
|
||||||
if let Some(ref i) = self.session.request {
|
if let Some(ref i) = self.session.request {
|
||||||
i.add(&self.address.client, &q)
|
i.add(&self.address.client, &q)
|
||||||
}
|
}
|
||||||
|
|
@ -51,10 +53,13 @@ impl Connection {
|
||||||
.clf(&self.address.client, Some(&q), 0, t);
|
.clf(&self.address.client, Some(&q), 0, t);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
t += self.response(Response::InternalServerError(format!(
|
t += self.response(Response::InternalServerError(
|
||||||
"[{}] < [{}] failed to handle incoming request: `{e}`",
|
"",
|
||||||
self.address.server, self.address.client
|
format!(
|
||||||
)));
|
"[{}] < [{}] failed to handle incoming request: `{e}`",
|
||||||
|
self.address.server, self.address.client
|
||||||
|
),
|
||||||
|
));
|
||||||
self.session
|
self.session
|
||||||
.access_log
|
.access_log
|
||||||
.clf(&self.address.client, None, 1, t);
|
.clf(&self.address.client, None, 1, t);
|
||||||
|
|
@ -87,50 +92,61 @@ impl Connection {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Response::InternalServerError(e) => {
|
Response::InternalServerError(q, e) => {
|
||||||
self.session.debug.error(&e);
|
eprintln!(
|
||||||
|
"[{}] > [{}] `{q}`: internal server error: `{e}`",
|
||||||
|
self.address.server, self.address.client
|
||||||
|
);
|
||||||
self.session.template.internal_server_error()
|
self.session.template.internal_server_error()
|
||||||
}
|
}
|
||||||
Response::AccessDenied(q) => {
|
Response::AccessDenied(q) => {
|
||||||
self.session.debug.error(&format!(
|
eprintln!(
|
||||||
"[{}] < [{}] access to `{q}` denied.",
|
"[{}] < [{}] access to `{q}` denied.",
|
||||||
self.address.server, self.address.client
|
self.address.server, self.address.client
|
||||||
));
|
);
|
||||||
self.session.template.access_denied()
|
self.session.template.access_denied()
|
||||||
}
|
}
|
||||||
Response::NotFound(q) => {
|
Response::NotFound(q) => {
|
||||||
self.session.debug.error(&format!(
|
eprintln!(
|
||||||
"[{}] < [{}] requested resource `{q}` not found.",
|
"[{}] < [{}] requested resource `{q}` not found.",
|
||||||
self.address.server, self.address.client
|
self.address.server, self.address.client
|
||||||
));
|
);
|
||||||
self.session.template.not_found()
|
self.session.template.not_found()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
match self.stream.write_all(bytes) {
|
match self.stream.write_all(bytes) {
|
||||||
Ok(()) => self.session.debug.info(&format!(
|
Ok(()) => {
|
||||||
"[{}] > [{}] sent {} bytes response.",
|
if self.session.is_debug {
|
||||||
self.address.server,
|
println!(
|
||||||
self.address.client,
|
"[{}] > [{}] sent {} bytes response.",
|
||||||
bytes.len()
|
self.address.server,
|
||||||
)),
|
self.address.client,
|
||||||
Err(e) => self.session.debug.error(&format!(
|
bytes.len()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => eprintln!(
|
||||||
"[{}] ! [{}] failed to response: `{e}`",
|
"[{}] ! [{}] failed to response: `{e}`",
|
||||||
self.address.server, self.address.client,
|
self.address.server, self.address.client,
|
||||||
)),
|
),
|
||||||
};
|
};
|
||||||
bytes.len()
|
bytes.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shutdown(self) {
|
fn shutdown(self) {
|
||||||
match self.stream.shutdown(std::net::Shutdown::Both) {
|
match self.stream.shutdown(std::net::Shutdown::Both) {
|
||||||
Ok(()) => self.session.debug.info(&format!(
|
Ok(()) => {
|
||||||
"[{}] - [{}] connection closed by server.",
|
if self.session.is_debug {
|
||||||
self.address.server, self.address.client,
|
println!(
|
||||||
)),
|
"[{}] - [{}] connection closed by server.",
|
||||||
Err(e) => self.session.debug.error(&format!(
|
self.address.server, self.address.client,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => eprintln!(
|
||||||
"[{}] > [{}] failed to close connection: `{e}`",
|
"[{}] > [{}] failed to close connection: `{e}`",
|
||||||
self.address.server, self.address.client,
|
self.address.server, self.address.client,
|
||||||
)),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,17 @@
|
||||||
mod access_log;
|
mod access_log;
|
||||||
mod debug;
|
|
||||||
mod public;
|
mod public;
|
||||||
mod request;
|
mod request;
|
||||||
mod template;
|
mod template;
|
||||||
|
|
||||||
use {access_log::AccessLog, debug::Debug, public::Public, request::Request, template::Template};
|
use {access_log::AccessLog, public::Public, request::Request, template::Template};
|
||||||
|
|
||||||
/// Shared, multi-thread features for the current server session
|
/// Shared, multi-thread features for the current server session
|
||||||
pub struct Session {
|
pub struct Session {
|
||||||
pub access_log: AccessLog,
|
pub access_log: AccessLog,
|
||||||
pub debug: Debug,
|
|
||||||
pub public: Public,
|
pub public: Public,
|
||||||
pub request: Option<Request>,
|
pub request: Option<Request>,
|
||||||
pub template: Template,
|
pub template: Template,
|
||||||
|
pub is_debug: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Session {
|
impl Session {
|
||||||
|
|
@ -20,7 +19,6 @@ impl Session {
|
||||||
let template = Template::init(config)?;
|
let template = Template::init(config)?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
access_log: AccessLog::init(config)?,
|
access_log: AccessLog::init(config)?,
|
||||||
debug: Debug::init(config)?,
|
|
||||||
public: Public::init(config)?,
|
public: Public::init(config)?,
|
||||||
request: if template.welcome.contains("{hosts}")
|
request: if template.welcome.contains("{hosts}")
|
||||||
|| template.welcome.contains("{hits}")
|
|| template.welcome.contains("{hits}")
|
||||||
|
|
@ -32,6 +30,7 @@ impl Session {
|
||||||
None // do not int request collector if its features not in use
|
None // do not int request collector if its features not in use
|
||||||
},
|
},
|
||||||
template,
|
template,
|
||||||
|
is_debug: config.debug,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
mod level;
|
|
||||||
use level::Level;
|
|
||||||
|
|
||||||
pub struct Debug(Vec<Level>);
|
|
||||||
|
|
||||||
impl Debug {
|
|
||||||
pub fn init(config: &crate::config::Config) -> anyhow::Result<Self> {
|
|
||||||
let mut l = Vec::with_capacity(config.debug.len());
|
|
||||||
for s in config.debug.to_lowercase().chars() {
|
|
||||||
l.push(Level::parse(s)?);
|
|
||||||
}
|
|
||||||
Ok(Self(l))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn error(&self, message: &str) {
|
|
||||||
if self.0.contains(&Level::Error) {
|
|
||||||
eprintln!("[{}] [error] {message}", now());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn info(&self, message: &str) {
|
|
||||||
if self.0.contains(&Level::Info) {
|
|
||||||
println!("[{}] [info] {message}", now());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn now() -> String {
|
|
||||||
chrono::Local::now().to_rfc3339()
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
use anyhow::{Result, bail};
|
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
|
||||||
pub enum Level {
|
|
||||||
Error,
|
|
||||||
Info,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Level {
|
|
||||||
pub fn parse(value: char) -> Result<Self> {
|
|
||||||
match value {
|
|
||||||
'e' => Ok(Self::Error),
|
|
||||||
'i' => Ok(Self::Info),
|
|
||||||
_ => bail!("unsupported debug level `{value}`!"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -61,7 +61,7 @@ impl Public {
|
||||||
Ok(t) => match (t.is_dir(), t.is_file()) {
|
Ok(t) => match (t.is_dir(), t.is_file()) {
|
||||||
(true, _) => callback(match self.list(&p) {
|
(true, _) => callback(match self.list(&p) {
|
||||||
Ok(list) => Response::Directory(query, list, p == self.public_dir),
|
Ok(list) => Response::Directory(query, list, p == self.public_dir),
|
||||||
Err(e) => Response::InternalServerError(e.to_string()),
|
Err(e) => Response::InternalServerError(query, e.to_string()),
|
||||||
}),
|
}),
|
||||||
(_, true) => match fs::File::open(p) {
|
(_, true) => match fs::File::open(p) {
|
||||||
Ok(mut f) => loop {
|
Ok(mut f) => loop {
|
||||||
|
|
@ -70,21 +70,24 @@ impl Public {
|
||||||
Ok(0) => break,
|
Ok(0) => break,
|
||||||
Ok(n) => callback(Response::File(&b[..n])),
|
Ok(n) => callback(Response::File(&b[..n])),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return callback(Response::InternalServerError(format!(
|
return callback(Response::InternalServerError(
|
||||||
"failed to read response chunk for `{query}`: `{e}`"
|
query,
|
||||||
)));
|
format!("failed to read response chunk: `{e}`"),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(e) => callback(Response::InternalServerError(format!(
|
Err(e) => callback(Response::InternalServerError(
|
||||||
"failed to read response for query`{query}`: `{e}`"
|
query,
|
||||||
))),
|
format!("failed to read response: `{e}`"),
|
||||||
|
)),
|
||||||
},
|
},
|
||||||
_ => panic!(), // unexpected
|
_ => panic!(), // unexpected
|
||||||
},
|
},
|
||||||
Err(e) => callback(Response::InternalServerError(format!(
|
Err(e) => callback(Response::InternalServerError(
|
||||||
"failed to read storage for `{query}`: `{e}`"
|
query,
|
||||||
))),
|
format!("failed to read storage: `{e}`"),
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue