use actix_request_identifier::{IdReuse, RequestIdentifier};
use actix_web::middleware::from_fn;
use actix_web::{middleware, web, App, HttpServer};
use crate::core::auth0::cookie_session::{self, CookieSessionSettings};
use crate::core::middlewares;
use crate::core::middlewares::force_keep_alive::force_keep_alive;
use crate::core::url_dispatch;
use crate::core::websocat::echo::server::EchoServer;
use crate::sitepages;
use crate::websocket::devstreams;
pub async fn run<F>(
ac: crate::server::AppContext,
server_name: &'static str,
cfg: F,
) -> Result<(), anyhow::Error>
where
F: Fn(&mut web::ServiceConfig, web::Data<crate::server::AppContext>) + Send + Clone + 'static,
{
let configuration = ac.config();
let context = web::Data::new(ac);
let address = format!("{}:{}", "0.0.0.0", configuration.application_port);
let address_clone = address.clone();
let protocal = configuration.protocal.clone();
let upstreams = configuration.upstreams.clone();
let cookie_session_settings = CookieSessionSettings::get(&configuration.cookie_session);
let devstreams = web::Data::new(devstreams::AppState::build());
let (echo_server, echo_connection_tx) = EchoServer::new(context.clone()).await;
let actorless_echo_server = tokio::spawn(echo_server.run());
let graphql_data = crate::graphql::build(context.clone());
let reqwest_client = reqwest::Client::default();
let new_app = move || {
let mut app = App::new()
.wrap(middleware::Compress::default())
.configure(url_dispatch::static_router)
.configure(url_dispatch::beautifier_js_router)
.configure(url_dispatch::favicon_router)
.wrap(cookie_session::session_cookie_store(&cookie_session_settings))
.wrap(cookie_session::flash_message(&cookie_session_settings).clone())
.wrap(crate::utils::cors())
.wrap(crate::utils::normalize_path_config())
.wrap(from_fn(force_keep_alive))
.wrap(RequestIdentifier::with_uuid().use_incoming_id(IdReuse::UseIncoming))
.wrap(middlewares::access_filter::Logger::get())
.wrap(crate::utils::default_headers()) ;
app = app
.app_data(web::Data::new(reqwest_client.clone()))
.app_data(web::Data::new(awc::Client::builder().finish()))
.app_data(web::Data::new(upstreams.clone()))
.app_data(context.tpl.clone())
.app_data(context.clone()) .app_data(devstreams.clone())
.app_data(web::Data::new(echo_connection_tx.clone()))
.app_data(web::Data::new(graphql_data.clone())) .app_data(crate::utils::path_variable_error_handler()) .app_data(crate::utils::post_json_error_handler()) .app_data(crate::utils::post_form_error_handler()) .app_data(crate::utils::multipart_form_error_handler()) .app_data(web::PayloadConfig::default().limit(10 * 1024 * 1024)) .app_data(crate::utils::query_error_handler());
app = app
.configure(|c| {
crate::server::serv::config(
c,
configuration.use_developer,
context.clone(),
upstreams.clone(),
)
})
.configure(|wc| cfg(wc, context.clone()));
app = app.default_service(actix_web::web::route().to(sitepages::default::not_found));
print_line(server_name, &protocal, &(address_clone));
app
};
let server = HttpServer::new(new_app)
.backlog(configuration.backlog_size)
.workers(if configuration.worker_count == 0 {
std::thread::available_parallelism()?.get()
} else {
configuration.worker_count
})
.shutdown_timeout(5)
.keep_alive(std::time::Duration::from_secs(configuration.keepalive_time));
let bind_result = if configuration.protocal == "http" {
server.bind(&address)
} else {
server.bind_openssl(
&address,
crate::commons::tls_builder((&configuration.https_key, &configuration.https_cert)),
)
};
match bind_result {
Ok(svr) => {
let http_server = svr.run();
tokio::try_join!(
http_server,
async move { actorless_echo_server.await.unwrap() },
)?;
Ok(())
}
Err(e) => {
#[rustfmt::skip]
log::info!("🔥 Couldn't start the server at port {}, error={}", &address, e );
Err(anyhow::anyhow!(e))
}
}
}
fn print_line(server_name: &str, protocal: &str, address: &str) {
let line = format!(
"{:>21} {}",
"Congratulations!", "Your server startup and running ~"
);
if !crate::core::cacheable::exists60s(&line) {
log::info!("{:>20}: {}", "Server Name", server_name);
log::info!("{:>20}: {}://{}", "Http Address", protocal, address);
log::info!(
"{:>20}: {}",
"Temporary Folder",
crate::commons::temp_folder(server_name)
);
log::info!(
"{:>20}: {}:00",
"Datetime Offset",
crate::commons::get_date_offsets()
);
log::info!("{}", line);
crate::core::cacheable::put60s(&line, "");
}
}