use std::io::{ErrorKind, Read, Write};
use std::net::{TcpListener, TcpStream};
use std::sync::Arc;
use std::{fs, io, thread};
use std::time::Duration;
use json::{JsonValue, object};
use log::info;
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
use crate::body::Body;
use crate::cors::Cors;
use crate::header::Header;
pub mod request;
mod cors;
pub mod header;
pub mod body;
#[derive(Clone, Debug)]
pub struct WebConfig {
pub url: String,
pub domain: String,
pub public: String,
pub temp_dir: String,
cors: Cors,
ssl: bool,
ssl_privkey: String,
ssl_certs: String,
}
impl WebConfig {
pub fn default() -> Self {
Self {
url: "127.0.0.1:3535".to_string(),
domain: "127.0.0.1:3535".to_string(),
public: "./public".to_string(),
temp_dir: "./temp".to_string(),
cors: Cors {
allow_origin: "*".to_string(),
allow_methods: "GET,POST".to_string(),
allow_headers: "api,token,mode,content-type".to_string(),
allow_credentials: false,
max_age: 10000000,
},
ssl: false,
ssl_privkey: "".to_string(),
ssl_certs: "".to_string(),
}
}
pub fn load(data: JsonValue) -> Self {
let ssl = data["ssl"].as_bool().unwrap_or(false);
let domain = if ssl {
format!("https://{}", data["domain"].as_str().unwrap_or(""))
} else {
format!("http://{}", data["domain"].as_str().unwrap_or(""))
};
Self {
url: data["url"].to_string(),
domain,
public: data["public"].to_string(),
temp_dir: data["temp_dir"].to_string(),
cors: Cors::load(data["cors"].clone()),
ssl,
ssl_privkey: data["ssl_privkey"].to_string(),
ssl_certs: data["ssl_certs"].to_string(),
}
}
pub fn to_json(self) -> JsonValue {
let mut data = object! {};
data["url"] = self.url.into();
data["domain"] = self.domain.into();
data["public"] = self.public.into();
data["temp_dir"] = self.temp_dir.into();
data["ssl"] = self.ssl.into();
data["ssl_privkey"] = self.ssl_privkey.into();
data["ssl_certs"] = self.ssl_certs.into();
data["cors"] = self.cors.to_json();
data
}
}
pub struct WebService {}
impl WebService {
pub fn bind(conf_path: &str, handle: fn(request: JsonValue) -> (i32, &'static str, JsonValue)) -> Result<(), io::Error> {
let conf = match fs::read_to_string(conf_path) {
Ok(content) => {
if content == "" {
return Err(io::Error::new(ErrorKind::BrokenPipe, "请配置配置文件参数"));
} else {
match json::parse(content.as_str()) {
Ok(e) => e,
Err(e) => {
return Err(io::Error::new(ErrorKind::BrokenPipe, e.to_string()));
}
}
}
}
Err(e) => {
if e.to_string().contains("No such file or directory") {
return Err(io::Error::new(ErrorKind::BrokenPipe, "请检查配置文件"));
}
return Err(io::Error::new(ErrorKind::BrokenPipe, e.to_string()));
}
};
let config = WebConfig::load(conf);
info!("web服务器启动 访问地址: {}",config.url);
info!("公共目录: {}", config.public);
info!("临时目录: {}", config.temp_dir);
info!("ssl开启: {}", config.ssl);
info!("根域名: {}", config.domain);
let acceptor = {
if config.ssl {
info!("privkey: {}", config.ssl_privkey.clone());
info!("certs: {}", config.ssl_certs.clone());
let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
acceptor.set_private_key_file(config.ssl_privkey.clone(), SslFiletype::PEM).unwrap();
acceptor.set_certificate_chain_file(config.ssl_certs.clone()).unwrap();
acceptor.check_private_key().unwrap();
Arc::new(acceptor.build())
} else {
Arc::new(SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap().build())
}
};
let config = config.clone();
loop {
let config = config.clone();
match TcpListener::bind(config.url.as_str().clone()) {
Ok(listener) => {
info!("服务启动成功");
for stream in listener.incoming() {
let header = Header { config: config.clone() };
let stream = stream.unwrap();
let acceptor = acceptor.clone();
thread::spawn(move || {
WebService::stream(stream.try_clone().unwrap(), acceptor.clone(), header.clone(), handle.clone());
});
}
}
Err(e) => {
info!("启动错误:{} 5秒后重启", e.to_string());
thread::sleep(Duration::from_secs(5));
}
}
}
}
pub fn stream(stream: TcpStream, acceptor: Arc<SslAcceptor>, header: Header, handle: fn(request: JsonValue) -> (i32, &'static str, JsonValue)) {
if header.config.ssl {
WebService::https(stream.try_clone().unwrap(), acceptor, header, handle);
} else {
WebService::http(stream.try_clone().unwrap(), header, handle);
}
}
pub fn http(mut stream: TcpStream, mut headers: Header, fun: fn(request: JsonValue) -> (i32, &'static str, JsonValue)) {
let client_ip = stream.local_addr().unwrap().clone();
let client_ip = client_ip.ip().to_string();
let mut buf = vec![];
let mut buffer = [0; 1024];
let mut count = 1024;
while count == 1024 {
count = stream.read(&mut buffer).unwrap();
buf = [buf, buffer[0..count].to_vec()].concat();
}
let data: String = buf.iter().map(|&c| c as char).collect();
let mut header = headers.def(data.clone());
header["client-ip"] = JsonValue::from(client_ip.clone());
let data_length = header["data-length"].as_usize().unwrap();
let body_length = header["content-length"].as_usize().unwrap();
let header_length = header["header-length"].as_usize().unwrap();
let mut mun = data_length - header_length;
while mun < body_length {
let mut buffer = [0; 1024];
let count = stream.read(&mut buffer).unwrap();
mun += count;
buf = [buf, buffer[0..count].to_vec()].concat();
};
let body = Body::def(header.clone(), buf[header_length..].to_owned().clone());
let (_, body) = request::Http::default(headers.config.cors.clone()).handle(header.clone(), body.clone(), fun);
stream.write_all(body.as_bytes()).unwrap();
stream.flush().unwrap();
}
pub fn https(stream: TcpStream, acceptor: Arc<SslAcceptor>, mut headers: Header, fun: fn(request: JsonValue) -> (i32, &'static str, JsonValue)) {
let client_ip = stream.local_addr().unwrap().clone();
let client_ip = client_ip.ip().to_string();
match acceptor.accept(stream) {
Ok(mut stream) => {
let mut buf = vec![];
let mut buffer = [0; 1024 * 10];
let mut count = 1024;
while count == 1024 {
count = stream.read(&mut buffer).unwrap();
buf = [buf, buffer[0..count].to_vec()].concat();
}
let data: String = buf.iter().map(|&c| c as char).collect();
let mut header = headers.def(data.clone());
header["client-ip"] = JsonValue::from(client_ip.clone());
let data_length = header["data-length"].as_usize().unwrap();
let body_length = header["content-length"].as_usize().unwrap();
let header_length = header["header-length"].as_usize().unwrap();
let mut mun = data_length - header_length;
while mun < body_length {
let mut buffer = [0; 1024];
let count = stream.read(&mut buffer).unwrap();
mun += count;
buf = [buf, buffer[0..count].to_vec()].concat();
};
let body = Body::def(header.clone(), buf[header_length..].to_owned().clone());
let (state, body) = request::Http::default(headers.config.cors.clone()).handle(header.clone(), body.clone(), fun);
if state {
stream.ssl_write(body.as_bytes()).unwrap();
stream.flush().unwrap();
}
}
Err(e) => {
info!("{}",e.to_string());
}
}
}
}