manserve/src/main.rs

89 lines
2.7 KiB
Rust
Raw Normal View History

2024-08-30 12:25:53 -04:00
use std::{
env,
process::{exit, Command},
time::Duration,
};
use axum::{
error_handling::HandleErrorLayer, extract::Path, http::StatusCode, response::Html,
routing::get, BoxError, Router,
};
use tower::{buffer::BufferLayer, limit::rate::RateLimitLayer, ServiceBuilder};
#[tokio::main]
async fn main() {
// initialize tracing
tracing_subscriber::fmt::init();
// idk how to have one rate limiting block apply to both of these but this works so it's fine
let app = Router::new()
.route(
"/:name",
get(command).layer(
ServiceBuilder::new()
.layer(HandleErrorLayer::new(|err: BoxError| async move {
(
StatusCode::INTERNAL_SERVER_ERROR,
format!("Unhandled error: {err}"),
)
}))
.layer(BufferLayer::new(1024))
.layer(RateLimitLayer::new(5, Duration::from_secs(1))),
),
)
.route(
"/",
get(StatusCode::BAD_REQUEST).layer(
ServiceBuilder::new()
.layer(HandleErrorLayer::new(|err: BoxError| async move {
(
StatusCode::INTERNAL_SERVER_ERROR,
format!("Unhandled error: {err}"),
)
}))
.layer(BufferLayer::new(1024))
.layer(RateLimitLayer::new(5, Duration::from_secs(1))),
),
);
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
println!("Provide a port with manserve $PORT");
exit(1);
}
if args[1].parse::<u16>().is_ok() {
let listener = tokio::net::TcpListener::bind(format!("0.0.0.0:{}", args[1]))
.await
.unwrap();
println!("Starting server on port {}", args[1]);
axum::serve(listener, app).await.unwrap();
} else {
println!("Could not parse port {}", args[1]);
exit(1);
}
}
async fn command(Path(name): Path<String>) -> Result<Html<String>, StatusCode> {
let mut manpage_loc = String::from_utf8(
Command::new("man")
.args(["-w", name.as_str()])
.output()
.unwrap()
.stdout,
)
.unwrap();
manpage_loc.pop();
let man = Command::new("mandoc")
.arg("-Thtml")
.arg("-O")
.arg("fragment")
.arg(manpage_loc)
.output()
.unwrap();
match man.status.success() {
true => Ok(Html(String::from_utf8(man.stdout).unwrap())),
false => Err(StatusCode::BAD_REQUEST),
}
}