It lives!
This commit is contained in:
parent
5245420073
commit
8a3dc6995c
|
|
@ -1,3 +1,4 @@
|
||||||
|
use rc_zip_tokio::ReadZip;
|
||||||
use std::convert::Infallible;
|
use std::convert::Infallible;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
|
@ -5,6 +6,7 @@ use axum::body::Body;
|
||||||
use http::{Method, Request, Response, StatusCode};
|
use http::{Method, Request, Response, StatusCode};
|
||||||
|
|
||||||
use crate::index::Entries;
|
use crate::index::Entries;
|
||||||
|
use crate::read_zip_for_arc::ArcBytes;
|
||||||
use crate::serve_zip::ZipServeConfig;
|
use crate::serve_zip::ZipServeConfig;
|
||||||
|
|
||||||
pub async fn serve<B>(
|
pub async fn serve<B>(
|
||||||
|
|
@ -57,13 +59,65 @@ fn not_found() -> Response<Body> {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn serve_entry(
|
async fn serve_entry(
|
||||||
_data: Arc<[u8]>,
|
data: Arc<[u8]>,
|
||||||
_config: ZipServeConfig,
|
config: ZipServeConfig,
|
||||||
_entry_name: String,
|
entry_name: String,
|
||||||
_method: Method,
|
method: Method,
|
||||||
) -> Result<Response<Body>, Infallible> {
|
) -> Result<Response<Body>, Infallible> {
|
||||||
Ok(Response::builder()
|
let data = ArcBytes(data);
|
||||||
.status(StatusCode::NOT_IMPLEMENTED)
|
let archive = match data.read_zip().await {
|
||||||
|
Ok(a) => a,
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Failed to open archive: {}", e);
|
||||||
|
return Ok(internal_error("Failed to open archive"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let entry = match archive.by_name(&entry_name) {
|
||||||
|
Some(e) => e,
|
||||||
|
None => return Ok(not_found()),
|
||||||
|
};
|
||||||
|
|
||||||
|
let content_type = mime_for(&entry_name, &config);
|
||||||
|
let content_length = entry.uncompressed_size;
|
||||||
|
|
||||||
|
if method == Method::HEAD {
|
||||||
|
return Ok(Response::builder()
|
||||||
|
.status(StatusCode::OK)
|
||||||
|
.header("content-type", content_type)
|
||||||
|
.header("content-length", content_length.to_string())
|
||||||
.body(Body::empty())
|
.body(Body::empty())
|
||||||
|
.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut reader = entry.reader();
|
||||||
|
let mut buffer = Vec::with_capacity(content_length as usize);
|
||||||
|
if let Err(e) = tokio::io::AsyncReadExt::read_to_end(&mut reader, &mut buffer).await {
|
||||||
|
eprintln!("Failed to read entry: {}", e);
|
||||||
|
return Ok(internal_error("Failed to read entry"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let body = Body::from(buffer);
|
||||||
|
|
||||||
|
Ok(Response::builder()
|
||||||
|
.status(StatusCode::OK)
|
||||||
|
.header("content-type", content_type)
|
||||||
|
.header("content-length", content_length.to_string())
|
||||||
|
.body(body)
|
||||||
.unwrap())
|
.unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mime_for(entry_name: &str, config: &ZipServeConfig) -> String {
|
||||||
|
mime_guess::from_path(entry_name)
|
||||||
|
.first_raw()
|
||||||
|
.unwrap_or(&config.fallback_content_type)
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn internal_error(msg: &str) -> Response<Body> {
|
||||||
|
Response::builder()
|
||||||
|
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||||
|
.header("content-type", "text/plain; charset=utf-8")
|
||||||
|
.body(Body::from(msg.to_string()))
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
pub mod handler;
|
pub mod handler;
|
||||||
pub mod index;
|
pub mod index;
|
||||||
|
pub mod read_zip_for_arc;
|
||||||
pub mod serve_zip;
|
pub mod serve_zip;
|
||||||
pub mod service;
|
pub mod service;
|
||||||
pub mod source;
|
pub mod source;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
use rc_zip::Error;
|
||||||
|
use rc_zip_tokio::{ArchiveHandle, HasCursor, ReadZip, ReadZipWithSize};
|
||||||
|
use std::io::Cursor;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
pub struct ArcBytes(pub Arc<[u8]>);
|
||||||
|
|
||||||
|
impl HasCursor for ArcBytes {
|
||||||
|
type Cursor<'a>
|
||||||
|
= Cursor<Arc<[u8]>>
|
||||||
|
where
|
||||||
|
Self: 'a;
|
||||||
|
|
||||||
|
fn cursor_at(&self, offset: u64) -> Self::Cursor<'_> {
|
||||||
|
let mut c = Cursor::new(Arc::clone(&self.0));
|
||||||
|
c.set_position(offset);
|
||||||
|
c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ReadZip for ArcBytes {
|
||||||
|
type File = Self;
|
||||||
|
async fn read_zip(&self) -> Result<ArchiveHandle<'_, Self>, Error> {
|
||||||
|
self.read_zip_with_size(self.0.len() as u64).await
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue