server/src/web.rs
Дамјан Георгиевски 98fbec274c enable the .tar handler
2020-09-14 23:44:00 +02:00

65 lines
2 KiB
Rust

use actix_web::{get, error, middleware, web, App, Error, HttpServer, HttpRequest, HttpResponse, Responder};
use actix_web::http::StatusCode;
use actix_files::{Files, NamedFile};
use futures::StreamExt;
use std::path::PathBuf;
pub async fn run(bind_addr: &str, root: &PathBuf) -> std::io::Result<()> {
let root_ = root.clone();
let s = HttpServer::new(move || {
let static_files = Files::new("/", &root_)
.show_files_listing()
.redirect_to_slash_directory()
.files_listing_renderer(crate::listing::directory_listing);
App::new()
.data(root_.clone())
.wrap(middleware::Logger::default())
.service(favicon_ico)
.service(handle_tar)
.service(static_files)
})
.bind(bind_addr)?
.run();
log::info!("Serving files from {:?}", &root);
s.await
}
#[get("/{tail:.*}.tar")]
async fn handle_tar(req: HttpRequest, root: web::Data<PathBuf>, web::Path(tail): web::Path<String>) -> impl Responder {
let relpath = PathBuf::from(tail.trim_end_matches('/'));
let fullpath = root.join(&relpath).canonicalize()
.map_err(|err| error::InternalError::new(err, StatusCode::INTERNAL_SERVER_ERROR))?;
if fullpath.is_file() {
return NamedFile::open(fullpath)
.map_err(|err| error::InternalError::new(err, StatusCode::INTERNAL_SERVER_ERROR))?
.into_response(&req);
}
if !(fullpath.is_dir()) {
return Ok(HttpResponse::NotFound().body("Directory not found"));
}
let stream = crate::threaded_archiver::stream_tar_in_thread(fullpath)
.map(|item| Ok::<_, Error>(item));
let res = HttpResponse::Ok()
.content_type("application/x-tar")
.streaming(stream);
Ok(res)
}
const FAVICON_ICO: &'static [u8] = include_bytes!("favicon.png");
#[get("/favicon.ico")]
async fn favicon_ico() -> impl Responder {
HttpResponse::Ok()
.content_type("image/png")
.header("Cache-Control", "only-if-cached, max-age=86400")
.body(FAVICON_ICO)
}