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::sync::Arc;
|
||||
|
||||
|
|
@ -5,6 +6,7 @@ use axum::body::Body;
|
|||
use http::{Method, Request, Response, StatusCode};
|
||||
|
||||
use crate::index::Entries;
|
||||
use crate::read_zip_for_arc::ArcBytes;
|
||||
use crate::serve_zip::ZipServeConfig;
|
||||
|
||||
pub async fn serve<B>(
|
||||
|
|
@ -57,13 +59,65 @@ fn not_found() -> Response<Body> {
|
|||
}
|
||||
|
||||
async fn serve_entry(
|
||||
_data: Arc<[u8]>,
|
||||
_config: ZipServeConfig,
|
||||
_entry_name: String,
|
||||
_method: Method,
|
||||
data: Arc<[u8]>,
|
||||
config: ZipServeConfig,
|
||||
entry_name: String,
|
||||
method: Method,
|
||||
) -> Result<Response<Body>, Infallible> {
|
||||
let data = ArcBytes(data);
|
||||
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())
|
||||
.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::NOT_IMPLEMENTED)
|
||||
.body(Body::empty())
|
||||
.status(StatusCode::OK)
|
||||
.header("content-type", content_type)
|
||||
.header("content-length", content_length.to_string())
|
||||
.body(body)
|
||||
.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 index;
|
||||
pub mod read_zip_for_arc;
|
||||
pub mod serve_zip;
|
||||
pub mod service;
|
||||
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