router/src/main.rs

108 lines
2.7 KiB
Rust
Raw Normal View History

use blocking::unblock;
use futures_lite::*;
use once_cell::sync::Lazy;
use sled::Db;
use tide::log::{self, LogMiddleware};
include!(concat!(env!("OUT_DIR"), "/templates.rs"));
mod iptables;
mod rules;
mod startup;
use self::{rules::Rule, startup::Interfaces, templates::statics::StaticFile};
static INTERFACES: Lazy<Interfaces> = Lazy::new(|| {
let interfaces = Interfaces::init_blocking().unwrap();
interfaces.reset_blocking().unwrap();
interfaces
});
static DB: Lazy<Db> = Lazy::new(|| sled::open("router-db-0-34-3").unwrap());
static QS: Lazy<serde_qs::Config> = Lazy::new(|| serde_qs::Config::new(3, false));
async fn rules_page(_: tide::Request<()>) -> tide::Result {
let mut html = Vec::new();
let rules = unblock(move || rules::read(&DB)).await?;
templates::rules(&mut html, &rules)?;
Ok(tide::Response::builder(200)
.body(html)
.content_type(
"text/html;charset=utf-8"
.parse::<tide::http::Mime>()
.unwrap(),
)
.build())
}
async fn save_rule(mut req: tide::Request<()>) -> tide::Result {
let body_string = req.body_string().await?;
let rule: Rule = QS.deserialize_str(&body_string)?;
rules::save(&DB, &rule).await?;
rules::apply(&INTERFACES, rule).await?;
Ok(to_rules_page())
}
async fn delete_rule(req: tide::Request<()>) -> tide::Result {
let id = req.param("id")?;
let rule = rules::delete(&DB, id).await?;
rules::unset(&INTERFACES, rule).await?;
Ok(to_rules_page())
}
fn to_rules_page() -> tide::Response {
tide::Response::builder(301)
.header("Location", "/rules")
.build()
}
async fn statics(req: tide::Request<()>) -> tide::Result {
let file: String = req.param("file")?;
if let Some(data) = StaticFile::get(&file) {
Ok(tide::Response::builder(200)
.header("Content-Type", data.mime.to_string())
.body(data.content)
.build())
} else {
Ok(tide::Response::builder(404).build())
}
}
fn main() -> Result<(), anyhow::Error> {
future::block_on(async {
println!("Hello, world!");
log::with_level(log::LevelFilter::Debug);
rules::apply_all(&DB, &INTERFACES).await?;
let mut app = tide::new();
app.with(LogMiddleware::new());
app.at("/static/:file").get(statics);
app.at("/rules").get(rules_page).post(save_rule);
app.at("/rules/:id").get(delete_rule);
let listeners: Vec<String> = INTERFACES
.internal
.iter()
.map(|info| format!("{}:8080", info.ip))
.collect();
app.listen(listeners).await?;
Ok(()) as Result<(), anyhow::Error>
})?;
Ok(())
}