feat: add error handling; update dockerfile

main
Jef Roosens 2025-01-01 21:17:18 +01:00
parent 391e45c09d
commit 6610442bf1
No known key found for this signature in database
GPG Key ID: 21FD3D77D56BAF49
3 changed files with 15 additions and 20 deletions

View File

@ -1,4 +1,4 @@
FROM rust:1.69-alpine3.16 AS builder FROM rust:1.83-alpine3.21 AS builder
ARG DI_VER=1.2.5 ARG DI_VER=1.2.5
@ -18,7 +18,7 @@ COPY . ./
RUN cargo build --release RUN cargo build --release
FROM alpine:3.16 FROM alpine:3.21
COPY --from=builder /app/target/release/site /bin/site COPY --from=builder /app/target/release/site /bin/site
COPY --from=builder /app/dumb-init /bin/dumb-init COPY --from=builder /app/dumb-init /bin/dumb-init

View File

@ -43,27 +43,17 @@ async fn main() {
let data_dir = PathBuf::from(std::env::var("DATA_DIR").expect("No DATA_DIR was provided.")); let data_dir = PathBuf::from(std::env::var("DATA_DIR").expect("No DATA_DIR was provided."));
let static_dir = data_dir.join(STATIC_DIR_NAME); let static_dir = data_dir.join(STATIC_DIR_NAME);
std::fs::create_dir_all(&static_dir); std::fs::create_dir_all(&static_dir).unwrap();
let state = Context { let state = Context {
static_dir, static_dir,
tmp_dir: std::env::temp_dir(), tmp_dir: std::env::temp_dir(),
}; };
tracing::info!("tmpdir = {}", state.tmp_dir.display());
// Initialize metrics // Initialize metrics
// let recorder_handle = metrics::setup_metrics_recorder(); // let recorder_handle = metrics::setup_metrics_recorder();
let app = server::app(state, &api_key, &REDIRECTS); let app = server::app(state, &api_key, &REDIRECTS);
// Each static site gets mounted explicitely so that the default site can be used as fallback
// Each entry is of the form (route, static dir name)
let sites = [
("/docs/vieter", "docs-vieter"),
("/api-docs/vieter", "api-docs-vieter"),
("/man/vieter", "man-vieter"),
];
let addr = SocketAddr::from(([0, 0, 0, 0], 3000)); let addr = SocketAddr::from(([0, 0, 0, 0], 3000));
let listener = TcpListener::bind(addr).await.unwrap(); let listener = TcpListener::bind(addr).await.unwrap();
tracing::debug!("listening on {}", addr); tracing::debug!("listening on {}", addr);

View File

@ -21,7 +21,7 @@ use std::{
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
use crate::STATIC_ROOT_NAME; use crate::{error::Result, STATIC_ROOT_NAME};
pub fn app( pub fn app(
ctx: crate::Context, ctx: crate::Context,
@ -41,6 +41,7 @@ pub fn app(
.route( .route(
"/{*path}", "/{*path}",
post(post_static_archive) post(post_static_archive)
.delete(delete_dir)
.route_layer(ValidateRequestHeaderLayer::bearer(api_key)) .route_layer(ValidateRequestHeaderLayer::bearer(api_key))
.get_service(serve_dir), .get_service(serve_dir),
) )
@ -58,16 +59,16 @@ pub async fn post_static_archive(
State(ctx): State<crate::Context>, State(ctx): State<crate::Context>,
extract::Path(path): extract::Path<String>, extract::Path(path): extract::Path<String>,
body: Body, body: Body,
) { ) -> Result<()> {
// Copy tarball data to file for parsing // Copy tarball data to file for parsing
let stream = body.into_data_stream(); let stream = body.into_data_stream();
let mut reader = StreamReader::new(stream.map_err(io::Error::other)); let mut reader = StreamReader::new(stream.map_err(io::Error::other));
let uuid = uuid::Uuid::new_v4(); let uuid = uuid::Uuid::new_v4();
let ar_path = ctx.tmp_dir.join(uuid.to_string()); let ar_path = ctx.tmp_dir.join(uuid.to_string());
let mut f = File::create(&ar_path).await; let mut f = File::create(&ar_path).await?;
tokio::io::copy(&mut reader, &mut f.unwrap()).await; tokio::io::copy(&mut reader, &mut f).await?;
// Root is stored in its own specifc directory, as otherwise it would wipe all other uploaded // Root is stored in its own specifc directory, as otherwise it would wipe all other uploaded
// directories every time it's updated // directories every time it's updated
@ -80,7 +81,9 @@ pub async fn post_static_archive(
tokio::task::spawn_blocking(move || process_archive(&ar_path, &dest_dir)) tokio::task::spawn_blocking(move || process_archive(&ar_path, &dest_dir))
.await .await
.unwrap(); .unwrap()?;
Ok(())
} }
fn process_archive(ar_path: &Path, dest_dir: &Path) -> io::Result<()> { fn process_archive(ar_path: &Path, dest_dir: &Path) -> io::Result<()> {
@ -116,7 +119,7 @@ fn process_archive(ar_path: &Path, dest_dir: &Path) -> io::Result<()> {
pub async fn delete_dir( pub async fn delete_dir(
State(ctx): State<crate::Context>, State(ctx): State<crate::Context>,
extract::Path(path): extract::Path<String>, extract::Path(path): extract::Path<String>,
) { ) -> Result<()> {
let dest_dir = if path.is_empty() { let dest_dir = if path.is_empty() {
String::from(crate::STATIC_ROOT_NAME) String::from(crate::STATIC_ROOT_NAME)
} else { } else {
@ -124,5 +127,7 @@ pub async fn delete_dir(
}; };
let dest_dir = ctx.static_dir.join(dest_dir); let dest_dir = ctx.static_dir.join(dest_dir);
tokio::fs::remove_dir_all(dest_dir).await; tokio::fs::remove_dir_all(dest_dir).await?;
Ok(())
} }