mod base64;
mod client;
pub mod config;
mod encoding;
pub mod request;
pub mod response;
pub mod websocket;
use crate::client::{Client, Scheme};
use crate::config::{Config};
use crate::request::Request;
use crate::response::Response;
use crate::websocket::{CloseCode, ErrorCode, Message, Websocket};
use log::{error, info, warn};
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
use std::io::{Error};
use std::net::{IpAddr, SocketAddr, TcpListener};
use std::sync::Arc;
use std::time::Duration;
use std::{io, thread};
#[derive(Clone, Debug)]
pub struct WebServer;
impl WebServer {
#[cfg(feature = "service")]
pub fn new_service(config: &Config, factory: fn(config: Config) -> Box<dyn Handler>) {
loop {
{
match WebServer::service(&config.clone(), factory) {
Ok(()) => {}
Err(e) => error!("服务器错误: {}[{}]: {}", file!(), line!(), e),
}
}
warn!("服务器 1秒后重启");
thread::sleep(Duration::from_secs(1));
}
}
#[cfg(feature = "service")]
fn service(config: &Config, factory: fn(config: Config) -> Box<dyn Handler>) -> io::Result<()> {
info!("==================== 网络服务 服务信息 ====================");
info!("日志记录: {}",if config.is_save_log {"开启"} else {"关闭"});
info!("调试模式: {}",if config.is_debug { "开启" } else { "关闭" });
info!("地 址: {}", config.host);
info!("端 口 号: {}", config.port);
info!("服务地址: {}://{}{}",if config.https { "https" } else { "http" },config.host,if config.port > 0 {format!(":{}", config.port)} else {String::new()});
info!("根 目 录: {}", config.root_path.to_str().unwrap());
info!("访问目录: {}", config.public);
info!("运行目录: {}", config.runtime);
info!("SSL/TLS: {}",if config.https { "开启" } else { "关闭" });
if config.https {
info!("证书目录KEY: {:?}", config.tls.key);
info!("证书目录PEM: {:?}", config.tls.certs);
}
let addrs = [SocketAddr::from((
IpAddr::V4(config.host.parse().unwrap()),
config.port,
))];
let listener = TcpListener::bind(&addrs[..])?;
info!("==================== 网络服务 启动成功 ====================");
let acceptor = Self::ssl(&config.clone())?;
for stream in listener.incoming() {
{
match stream {
Ok(stream) => {
let config_new = config.clone();
let acceptor_new = acceptor.clone();
thread::spawn(move || {
if config_new.write_timeout > 0 {
stream.set_write_timeout(Some(Duration::from_secs(config_new.write_timeout))).unwrap_or_default();
}
if config_new.read_timeout > 0 {
stream.set_read_timeout(Some(Duration::from_secs(config_new.read_timeout))).unwrap_or_default();
}
let client_ip = stream.peer_addr().unwrap().ip().to_string();
let server_ip = stream.local_addr().unwrap().ip().to_string();
let scheme = if config_new.https {
match acceptor_new.accept(stream.try_clone().unwrap()) {
Ok(e) => Scheme::Https(e, client_ip.clone()),
Err(_) => return,
}
} else {
Scheme::Http(stream.try_clone().unwrap(), client_ip.clone())
};
let mut client = Client {
config: config_new.clone(),
request: Request::default(config_new.root_path.clone()),
response: Response::default(config_new.root_path),
server_ip,
client_ip,
factory,
proxy_ip: String::new(),
};
match client.handle_service(scheme) {
Ok(()) => {}
Err(e) => error!("{e}"),
}
});
}
Err(e) => return Err(e),
}
}
}
Ok(())
}
#[cfg(feature = "webpage")]
pub fn new_webpage(config: &Config, factory: fn(config: Config) -> Box<dyn Handler>) {
loop {
match WebServer::webpage(&config.clone(), factory) {
Ok(()) => {}
Err(e) => error!("{}[{}]: {}", file!(), line!(), e),
}
warn!("服务器 2秒后重启");
thread::sleep(Duration::from_secs(2));
}
}
#[cfg(feature = "webpage")]
fn webpage(config: &Config, factory: fn(config: Config) -> Box<dyn Handler>) -> io::Result<()> {
info!("==================== 网页服务 服务信息 ====================");
info!(
"日志记录: {}",
if config.is_save_log {
"开启"
} else {
"关闭"
}
);
info!(
"调试模式: {}",
if config.is_debug { "开启" } else { "关闭" }
);
info!("地 址: {}", config.host);
info!("端 口 号: {}", config.port);
info!(
"服务地址: {}://{}{}",
if config.https { "https" } else { "http" },
config.host,
if config.port > 0 {
format!(":{}", config.port)
} else {
String::new()
}
);
info!("网页目录: {}", config.public);
info!(
"SSL/TLS: {}",
if config.https { "开启" } else { "关闭" }
);
if config.https {
info!("证书目录KEY: {:?}", config.tls.key);
info!("证书目录PEM: {:?}", config.tls.certs);
}
let addrs = [SocketAddr::from((
IpAddr::V4(config.host.parse().unwrap()),
config.port,
))];
let listener = TcpListener::bind(&addrs[..])?;
info!("==================== 网页服务 启动成功 ====================");
let acceptor = Self::ssl(&config.clone())?;
for stream in listener.incoming() {
match stream {
Ok(stream) => {
let config_new = config.clone();
let acceptor = acceptor.clone();
thread::spawn(move || {
if config_new.write_timeout > 0 {
stream.set_write_timeout(Some(Duration::from_secs(
config_new.write_timeout,
))).unwrap_or_default();
}
if config_new.read_timeout > 0 {
stream.set_read_timeout(Some(Duration::from_secs(
config_new.read_timeout,
))).unwrap_or_default();
}
let client_ip = stream.peer_addr().unwrap().to_string();
let server_ip = stream.local_addr().unwrap().to_string();
let scheme = if config_new.https {
match acceptor.accept(stream.try_clone().unwrap()) {
Ok(e) => Scheme::Https(e, client_ip.clone()),
Err(_) => return,
}
} else {
Scheme::Http(stream.try_clone().unwrap(), client_ip.clone())
};
let client = Client {
config: config_new.clone(),
request: Request::default(config_new.root_path.clone()),
response: Response::default(config_new.root_path.clone()),
factory,
server_ip,
client_ip,
proxy_ip: String::new(),
};
match client.handle_webpage(scheme) {
Ok(()) => {}
Err(e) => error!("{e}"),
}
});
}
Err(e) => return Err(e),
}
}
Ok(())
}
fn ssl(config: &Config) -> io::Result<Arc<SslAcceptor>> {
if config.https {
let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls())?;
if !config.tls.key.is_file() {
return Err(Error::other(
format!("private.key 不存在: {:?}", config.tls.key).as_str(),
));
}
if !config.tls.certs.is_file() {
return Err(Error::other(
format!("certificate.pem 不存在: {:?}", config.tls.certs).as_str(),
));
}
acceptor.set_private_key_file(config.tls.key.clone(), SslFiletype::PEM)?;
acceptor.set_certificate_file(config.tls.certs.clone(), SslFiletype::PEM)?;
Ok(Arc::new(acceptor.build()))
} else {
Ok(Arc::new(SslAcceptor::mozilla_intermediate(SslMethod::tls())?.build()))
}
}
}
pub trait Handler {
#[cfg(any(feature = "webpage", feature = "service"))]
fn on_request(&mut self, request: Request, response: Response) -> Response;
#[cfg(any(feature = "webpage", feature = "service"))]
fn on_options(&mut self, _request: Request, mut response: Response) -> Response {
response.header("Access-Control-Allow-Origin", "*");
response.header("Access-Control-Allow-Methods", "*");
response.header("Access-Control-Allow-Headers", "*");
response.header("Access-Control-Allow-Credentials", "true");
response.header("Access-Control-Expose-Headers", "content-disposition");
response.header("Access-Control-Max-Age", "0");
response
}
#[cfg(any(feature = "service", feature = "webpage"))]
fn on_response(&mut self, request: Request, mut response: Response) -> Response {
if response.config.origin.is_empty() {
response.header("Access-Control-Allow-Origin", "*");
} else {
let origin = request.header["origin"].as_str().unwrap_or("");
if !origin.is_empty() && response.config.origin.contains(&origin.to_string().clone()) {
response.header("Access-Control-Allow-Origin", origin);
}
}
if response.headers.has_key("Content-Disposition") {
response.header("Access-Control-Expose-Headers", "content-disposition");
}
response
}
fn on_open(&mut self, _websocket: Websocket) -> io::Result<()> {
Ok(())
}
fn on_message(&mut self, _msg: Message) -> io::Result<()> {
Ok(())
}
fn on_close(&mut self, _code: CloseCode, _reason: &str) {}
fn on_error(&mut self, _err: ErrorCode) {}
fn on_shutdown(&mut self) {}
fn on_ping(&mut self, _msg: Message) {}
fn on_pong(&mut self, _msg: Message) {}
}