use actix_web::middleware::Condition;
use lazy_static::lazy_static;
use actix_web::http::Method;
use actix_web::web;
use actix_web::HttpRequest;
use actix_web::Route;
use actix_web::{web::ServiceConfig, Responder};
use actix_web::middleware::from_fn;
use crate::commons;
use crate::core::auth0::Authorized;
use crate::core::auth0::Protected;
use crate::core::cacheable::YourCache;
use crate::core::middlewares::request_id;
use crate::server::AppContext;
use crate::core::csrf::CsrfMiddleware;
lazy_static! {
static ref CACHE_KEY: &'static str = "__URL_COUNT";
static ref RS_CACHE_60S: YourCache::<usize> = YourCache::build(60, 5 * 1024 * 1024);
}
#[allow(deprecated)]
pub fn url_dispatch<F, Args>(
cfg: &mut ServiceConfig,
app_state: actix_web::web::Data<AppContext>,
method: &str,
protected: &Protected,
path: &str,
handler: F,
) where
F: actix_web::Handler<Args>,
Args: actix_web::FromRequest + 'static,
F::Output: actix_web::Responder + 'static,
{
let line = if !path.contains("forward:") {
format!(
"url-dispatch: {} {} > {}",
&method.to_uppercase(),
&path,
get_function_name(&handler)
)
} else {
format!(
"url-upstream: {} {} > {}",
&method.to_uppercase(),
&path,
get_function_name(&handler)
)
};
if !crate::core::cacheable::exists60s(&line) {
log::info!(
"({}){}",
format_args!("{:0>width$}", incr(), width = 3),
line
);
crate::core::cacheable::put60s(&line, "");
}
if method == "*" || method == "Any" {
cfg.service(
web::resource(path)
.wrap(from_fn(request_id))
.route(actix_web::web::get().to(handler.clone()))
.route(actix_web::web::post().to(handler.clone()))
.route(actix_web::web::delete().to(handler.clone()))
.route(actix_web::web::put().to(handler.clone()))
.route(actix_web::web::patch().to(handler.clone())),
);
} else {
let method = Method::from_bytes(method.to_uppercase().trim().as_bytes()).unwrap();
cfg.service(
web::resource(path)
.wrap(from_fn(request_id))
.wrap(Condition::new(path == "/login", CsrfMiddleware::new()))
.wrap(Condition::new(path == "/signup", CsrfMiddleware::new()))
.wrap(Authorized::builder(app_state, protected.to_owned()))
.route(Route::new().method(method).to(handler))
.default_service(web::route().to(crate::sitepages::default::e405)),
);
}
}
async fn favicon(_req: HttpRequest) -> std::io::Result<actix_files::NamedFile> {
actix_files::NamedFile::open(format!(
"{}/favicon.ico",
commons::read_env("static", "./RichMedias")
))
}
async fn favicon_svg() -> impl Responder {
actix_files::NamedFile::open_async(format!(
"{}/favicon.svg",
commons::read_env("static", "./RichMedias")
))
.await
.unwrap()
}
pub fn static_router(config: &mut ServiceConfig) {
let fs = actix_files::Files::new("/RichMedias", commons::read_env("static", "./RichMedias"));
config.service(fs);
}
async fn beautifier_js(_req: HttpRequest) -> std::io::Result<actix_files::NamedFile> {
actix_files::NamedFile::open(format!(
"{}/beautifier.min.js",
commons::read_env("static", "./RichMedias/js_beautify/js/lib")
))
}
pub fn beautifier_js_router(config: &mut ServiceConfig) {
config
.route(
"/developer/js/lib/beautifier.min.js",
web::get().to(beautifier_js),
)
.default_service(actix_web::web::route().to(crate::sitepages::default::e405));
}
pub fn favicon_router(config: &mut ServiceConfig) {
config
.route("/favicon.ico", web::get().to(favicon))
.route("/favicon.svg", web::get().to(favicon_svg))
.default_service(actix_web::web::route().to(crate::sitepages::default::e405));
}
fn incr() -> usize {
match RS_CACHE_60S.get(*CACHE_KEY) {
Some(val) => {
RS_CACHE_60S.put(*CACHE_KEY, val + 1);
val + 1
}
None => {
RS_CACHE_60S.put(*CACHE_KEY, 1);
1
}
}
}
fn get_function_name<F, Args>(_: &F) -> &'static str
where
F: actix_web::Handler<Args>,
Args: actix_web::FromRequest + 'static,
F::Output: actix_web::Responder + 'static,
{
std::any::type_name::<F>()
}