feat: Serve index.html at root
This commit is contained in:
parent
f42924cd3b
commit
256aca663c
1 changed files with 23 additions and 8 deletions
|
@ -1,6 +1,6 @@
|
|||
use std::{io::{self, Read}, path::PathBuf, path, fs::File};
|
||||
|
||||
use axum::{http::{StatusCode, HeaderMap, HeaderValue}, extract::{Multipart, Path}, body::Bytes, BoxError, Router, routing::{post, get}};
|
||||
use axum::{http::{StatusCode, HeaderMap, HeaderValue}, extract::{Multipart, Path}, body::Bytes, BoxError, Router, routing::{post, get}, response::Redirect};
|
||||
use futures::{Stream, TryStreamExt};
|
||||
use tokio::io::{BufWriter, AsyncWriteExt};
|
||||
use tokio_util::io::StreamReader;
|
||||
|
@ -11,29 +11,44 @@ use crate::projects::Authed;
|
|||
pub fn router() -> Router {
|
||||
Router::new()
|
||||
.route("/:project", post(upload_project))
|
||||
.route("/:project", get(project_redirect))
|
||||
.route("/:project/*path", get(get_asset))
|
||||
}
|
||||
|
||||
async fn project_redirect(Path(path): Path<String>) -> Redirect {
|
||||
Redirect::to(&format!("/{}/", path))
|
||||
}
|
||||
|
||||
async fn get_asset(Path((project, filename)): Path<(String, String)>) -> Result<(HeaderMap, Vec<u8>), StatusCode> {
|
||||
let path = path::Path::new("project-archives")
|
||||
.join(format!("{project}.zip"));
|
||||
if path.exists() {
|
||||
let data = {
|
||||
let asset = {
|
||||
let filename = filename.clone();
|
||||
move || {
|
||||
let zip = ZipArchive::new(File::open(path)?)?;
|
||||
let asset = find_asset(zip, &filename.clone())?;
|
||||
let mut zip = ZipArchive::new(File::open(path)?)?;
|
||||
let asset = find_asset(&mut zip, &filename.clone())?;
|
||||
let asset = if let Some(asset) = asset {
|
||||
Some((mime_guess::from_path(filename).first_or_octet_stream(), asset))
|
||||
} else if filename.ends_with("/") {
|
||||
let changed_name = format!("{filename}index.html");
|
||||
find_asset(&mut zip, &changed_name)?
|
||||
.map(|data| (mime_guess::from_path(changed_name).first_or_octet_stream(), data))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok::<_, color_eyre::Report>(asset)
|
||||
}
|
||||
};
|
||||
let data = tokio::task::spawn_blocking(data).await
|
||||
|
||||
let asset = tokio::task::spawn_blocking(asset).await
|
||||
.unwrap()
|
||||
.map_err(|e| {
|
||||
tracing::error!(%e, "failed to find asset in zip");
|
||||
StatusCode::INTERNAL_SERVER_ERROR
|
||||
})?;
|
||||
if let Some(data) = data {
|
||||
let mime = mime_guess::from_path(filename).first_or_octet_stream();
|
||||
|
||||
if let Some((mime, data)) = asset {
|
||||
let mut headers = HeaderMap::new();
|
||||
headers.append("content-type", HeaderValue::from_str(mime.essence_str()).unwrap());
|
||||
Ok((headers, data))
|
||||
|
@ -45,7 +60,7 @@ async fn get_asset(Path((project, filename)): Path<(String, String)>) -> Result<
|
|||
}
|
||||
}
|
||||
|
||||
fn find_asset(mut zip: ZipArchive<impl std::io::Read + std::io::Seek>, filename: &str) -> color_eyre::Result<Option<Vec<u8>>> {
|
||||
fn find_asset(zip: &mut ZipArchive<impl std::io::Read + std::io::Seek>, filename: &str) -> color_eyre::Result<Option<Vec<u8>>> {
|
||||
let filename = if filename.starts_with("/") {
|
||||
&filename[1..]
|
||||
} else {
|
||||
|
|
Loading…
Reference in a new issue