Gouzi Mohaled
Ajout du dossier lib
84d2a97
use std::error::Error;
use std::path::PathBuf;
use std::pin::Pin;
use actix_files::NamedFile;
use actix_web::http::header::ContentDisposition;
use actix_web::{HttpResponse, Responder};
use bytes::Bytes;
use futures::{Stream, TryStreamExt};
pub struct SnapShotStreamLocalFS {
pub snapshot_path: PathBuf,
}
type ByteStream = Pin<Box<dyn Stream<Item = Result<Bytes, Box<dyn Error>>>>>;
pub struct SnapShotStreamCloudStrage {
stream: ByteStream,
filename: Option<String>,
}
pub enum SnapshotStream {
LocalFS(SnapShotStreamLocalFS),
ByteStream(SnapShotStreamCloudStrage),
}
impl SnapshotStream {
/// Create a new snapshot stream from a byte stream.
///
/// The `filename` is used as the `Content-Disposition` header and only
/// makes sense when the snapshot needs to be saved under a different
/// name than the endpoint path.
pub fn new_stream<S, E>(stream: S, filename: Option<String>) -> Self
where
S: Stream<Item = Result<Bytes, E>> + 'static,
E: Into<Box<dyn Error>>,
{
SnapshotStream::ByteStream(SnapShotStreamCloudStrage {
stream: Box::pin(stream.map_err(|e| e.into())),
filename,
})
}
}
impl Responder for SnapshotStream {
type Body = actix_web::body::BoxBody;
fn respond_to(self, req: &actix_web::HttpRequest) -> HttpResponse<Self::Body> {
match self {
SnapshotStream::LocalFS(stream) => match NamedFile::open(stream.snapshot_path) {
Ok(file) => file.into_response(req),
Err(e) => match e.kind() {
std::io::ErrorKind::NotFound => {
HttpResponse::NotFound().body(format!("File not found: {e}"))
}
_ => HttpResponse::InternalServerError()
.body(format!("Failed to open file: {e}")),
},
},
SnapshotStream::ByteStream(SnapShotStreamCloudStrage { stream, filename }) => {
let mut response = HttpResponse::Ok();
response.content_type("application/octet-stream");
if let Some(filename) = filename {
response.insert_header(ContentDisposition::attachment(filename));
}
response.streaming(stream)
}
}
}
}