Initial commit.

This commit is contained in:
2025-10-17 05:37:48 -05:00
commit cb4c8b3838
7 changed files with 1708 additions and 0 deletions

96
src/main.rs Normal file
View File

@@ -0,0 +1,96 @@
use axum::{
BoxError, Router,
error_handling::HandleErrorLayer,
extract::{DefaultBodyLimit, Multipart},
http::StatusCode,
response::{Html, IntoResponse, Response},
routing::{get, post},
};
use clap::Parser;
use color_eyre::eyre::Result;
use std::time::Duration;
use tokio::fs;
use tower::{ServiceBuilder, buffer::BufferLayer, limit::rate::RateLimitLayer};
use tower_http::{compression::CompressionLayer, limit::RequestBodyLimitLayer, trace::TraceLayer};
mod store;
#[derive(Parser, Debug)]
#[command(version, about)]
struct Args {
/// Configuration file locaation.
#[arg(short, long)]
config: String,
}
async fn default_handler() -> Response {
match fs::read_to_string("index.html").await {
Ok(content) => Html(content).into_response(),
Err(e) => (
axum::http::StatusCode::INTERNAL_SERVER_ERROR,
format!("Failed to read index.html: {}", e),
)
.into_response(),
}
}
async fn handle_error(err: BoxError) -> (StatusCode, String) {
if err.is::<tower::timeout::error::Elapsed>() {
(StatusCode::REQUEST_TIMEOUT, "Request timed out".to_string())
} else if err.is::<tower::load_shed::error::Overloaded>() {
(
StatusCode::SERVICE_UNAVAILABLE,
"Service overloaded, try again later".to_string(),
)
} else {
(
StatusCode::INTERNAL_SERVER_ERROR,
format!("Internal error: {}", err),
)
}
}
async fn upload_handler(mut _multipart: Multipart) -> Response {
// while let field = multipart.next_field().await {
// match field {
// Ok(field) => (StatusCode::OK, "Insert Link Here...".to_string()).into_response(),
// Err(err) => (
// StatusCode::BAD_REQUEST,
// format!("Error processing request: {}", err),
// )
// .into_response(),
// }
// }
unimplemented!()
}
#[tokio::main]
async fn main() -> Result<()> {
color_eyre::install()?;
tracing_subscriber::fmt::init();
let _args = Args::parse();
let app = Router::new()
.route("/", get(default_handler))
.route("/", post(upload_handler))
.layer(
ServiceBuilder::new()
.layer(HandleErrorLayer::new(handle_error))
.layer(TraceLayer::new_for_http())
// Set to about the expected number of concurrent connections.
.layer(BufferLayer::new(64))
// Limit to 30 per minute
.layer(RateLimitLayer::new(30, Duration::from_secs(60)))
.layer(RequestBodyLimitLayer::new(1024 * 1024))
.layer(DefaultBodyLimit::disable())
.layer(CompressionLayer::new()),
);
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
.await
.unwrap();
axum::serve(listener, app).await.unwrap();
Ok(())
}

8
src/store/keyval/mod.rs Normal file
View File

@@ -0,0 +1,8 @@
// Default rocksdb storage.
use color_eyre::eyre::Result;
#[allow(dead_code)]
pub async fn init(_path: impl AsRef<str>) -> Result<()> {
Ok(())
}

1
src/store/mod.rs Normal file
View File

@@ -0,0 +1 @@
pub(crate) mod keyval;