use std::{env, process, thread, time::Duration};
use encoding::StreamReader;
use http_srv::prelude::*;
use libloading::{Library, Symbol};
type Result<T> = ::core::result::Result<T, libloading::Error>;
fn load_lib(handler: &mut Handler, name: &str) -> Result<Library> {
unsafe {
let lib = libloading::Library::new(name)?;
let init_handler: Symbol<fn(*mut Handler)> = lib.get(b"init_handler")?;
init_handler(handler);
Ok(lib)
}
}
fn get_handler(config: &ServerConfig) -> Result<(Option<Library>, Handler)> {
let mut handler = match config.preset {
Preset::Read => handler::presets::read(),
Preset::ReadWrite => handler::presets::read_write(),
Preset::Post => handler::presets::post(),
};
let mut _lib = None;
if let Some(path) = &config.setup_lib {
let mut handler = Handler::new();
_lib = Some(load_lib(&mut handler, path)?);
return Ok((_lib, handler));
}
handler.get("/sleep", |req: &mut HttpRequest| {
thread::sleep(Duration::from_secs(5));
req.ok()
});
handler.get("/params", |req: &mut HttpRequest| {
let mut s = "".to_string();
for (k, v) in req.params() {
s.push_str(k);
s.push_str(" = ");
s.push_str(v);
s.push('\n');
}
req.respond_str(&s)
});
handler.get("/inf", |req: &mut HttpRequest| {
let mut i = 0;
let chars = b"hello, world!\n";
let inf = || {
if i >= chars.len() {
i = 0;
}
i += 1;
Some(chars[i - 1])
};
let mut reader = StreamReader::new(inf);
req.respond_reader(&mut reader)
});
handler.get("/hello", |req: &mut HttpRequest| {
let name = req.param("name").unwrap_or("friend");
let msg = format!("Hello {name}!");
req.respond_str(&msg)
});
handler.get("/redirect", handler::redirect("/hello"));
#[cfg(feature = "regex")]
handler.get(
handler::UrlMatcher::regex(".*\\.php$").unwrap(),
|req: &mut HttpRequest| {
use std::{
path::Path,
process::{Command, Stdio},
};
let fname = &*req.filename().unwrap();
if !Path::new(fname).exists() {
return req.set_status(404).respond_error_page();
}
let output = Command::new("php")
.arg(fname)
.stdout(Stdio::piped())
.spawn()?
.wait_with_output()?;
if !output.status.success() {
req.server_error()
} else {
req.respond_buf(&output.stdout)
}
},
);
if let Some(file) = &config.log_file {
handler.post_interceptor(handler::log_file(file).unwrap_or_else(|err| {
eprintln!("{err}");
process::exit(1);
}));
}
let auth = AuthConfig::of_list(&[("test", "test"), ("abc", "abc")]);
handler.get(
"/priv",
auth.apply(|req: &mut HttpRequest| req.respond_str("Secret message")),
);
Ok((_lib, handler))
}
pub fn main() {
let args: Vec<_> = env::args().skip(1).collect();
let config = ServerConfig::parse(&args).unwrap_or_else(|err| {
eprintln!("{err}");
process::exit(1);
});
let (_lib, handler) = get_handler(&config).unwrap_or_else(|err| {
eprintln!("ERROR: {err}");
process::exit(1);
});
let mut server = HttpServer::new(config).unwrap_or_else(|err| {
eprintln!("ERROR: {err}");
std::process::exit(1)
});
server.set_handler(handler);
server.run();
}