Added some argument handling.

This commit is contained in:
Micheal Smith
2025-10-20 08:19:29 -05:00
parent cb4c8b3838
commit 06339ca8ab
4 changed files with 179 additions and 143 deletions

View File

@@ -1,3 +1,6 @@
// TODO: Add general description of the workings.
// TODO: Add ability to run a temporary pastebin
use axum::{
BoxError, Router,
error_handling::HandleErrorLayer,
@@ -8,10 +11,12 @@ use axum::{
};
use clap::Parser;
use color_eyre::eyre::Result;
use std::time::Duration;
use nanoid::nanoid;
use std::{path::PathBuf, time::Duration};
use tokio::fs;
use tower::{ServiceBuilder, buffer::BufferLayer, limit::rate::RateLimitLayer};
use tower_http::{compression::CompressionLayer, limit::RequestBodyLimitLayer, trace::TraceLayer};
use tracing::{Level, event};
mod store;
@@ -19,8 +24,24 @@ mod store;
#[command(version, about)]
struct Args {
/// Configuration file locaation.
#[arg(short, long)]
config: String,
#[arg(short, long, value_name = "FILE")]
config: Option<PathBuf>,
/// Address to listen on.
#[arg(short, long, default_value = "localhost")]
listen_address: String,
/// Port to listen on.
#[arg(short, long, default_value_t = 3000)]
port: u16,
/// Largest file size accepted.
#[arg(short, long, default_value_t = 1024, value_name = "SIZE_IN_KB")]
max_request_size: usize,
/// Set the number of requests handled per minute.
#[arg(short, long, default_value_t = 30)]
requests_per_min: u64,
}
async fn default_handler() -> Response {
@@ -50,27 +71,47 @@ async fn handle_error(err: BoxError) -> (StatusCode, String) {
}
}
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(),
async fn upload_handler(mut multipart: Multipart) -> Response {
while let Ok(Some(part)) = multipart.next_field().await {
if let Some(name) = part.name()
&& name == "file"
{
println!("Got: {}", name);
}
}
// Err(err) => (
// StatusCode::BAD_REQUEST,
// format!("Error processing request: {}", err),
// )
// .into_response(),
// }
// }
unimplemented!()
(StatusCode::OK, nanoid!()).into_response()
}
// Defaults to info level tracing, but can be adjusted using the
// RUST_LOG environment variable.
fn install_tracing() {
use tracing_error::ErrorLayer;
use tracing_subscriber::prelude::*;
use tracing_subscriber::{EnvFilter, fmt};
let fmt_layer = fmt::layer().with_target(false);
let filter_layer = EnvFilter::try_from_default_env()
.or_else(|_| EnvFilter::try_new("info"))
.unwrap();
tracing_subscriber::registry()
.with(filter_layer)
.with(fmt_layer)
.with(ErrorLayer::default())
.init();
}
#[tokio::main]
async fn main() -> Result<()> {
color_eyre::install()?;
tracing_subscriber::fmt::init();
install_tracing();
let _args = Args::parse();
color_eyre::install()?;
let args = Args::parse();
let request_limit = args.requests_per_min;
let max_size = args.max_request_size;
let listen_address = format!("{}:{}", args.listen_address, args.port);
let app = Router::new()
.route("/", get(default_handler))
@@ -82,15 +123,14 @@ async fn main() -> Result<()> {
// 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(RateLimitLayer::new(request_limit, Duration::from_secs(60)))
.layer(RequestBodyLimitLayer::new(max_size * 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();
let listener = tokio::net::TcpListener::bind(listen_address.to_owned()).await?;
event!(Level::INFO, "Now listening on {}.", listen_address);
axum::serve(listener, app).await?;
Ok(())
}

View File

@@ -1,8 +1,27 @@
// Default rocksdb storage.
use bytes::Bytes;
use color_eyre::eyre::Result;
use nanoid::nanoid;
use rocksdb::{DB, Options};
use std::path::{Path, PathBuf};
#[allow(dead_code)]
pub async fn init(_path: impl AsRef<str>) -> Result<()> {
Ok(())
}
pub struct KeyVal {
db_path: PathBuf,
}
impl KeyVal {
pub fn new(database_path: impl AsRef<Path>) -> Result<KeyVal> {
Ok(KeyVal { db_path: database_path.as_ref().into() })
}
// Store value into the database, and return the key that was assigned to it.
pub async fn store(&self, data: impl AsRef<[u8]>) -> Result<String> {
Ok(nanoid!())
}
}