From 89e72d00ae2ef934e359f4502e816c82e4c958cc Mon Sep 17 00:00:00 2001 From: Antoine Gersant Date: Sun, 28 Oct 2018 12:21:46 -0700 Subject: [PATCH] Partial implementation of the serve endpoint --- src/errors.rs | 11 +++++++++++ src/rocket_api.rs | 43 ++++++++++++++++++++++++++++++++++--------- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/src/errors.rs b/src/errors.rs index 18f453e..ba97132 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -11,6 +11,7 @@ use iron::IronError; use lewton; use metaflac; use regex; +use rocket; use rustfm_scrobble; use serde_json; use std; @@ -60,6 +61,16 @@ error_chain! { } } +impl<'r> rocket::response::Responder<'r> for Error { + fn respond_to(self, _: &rocket::request::Request) -> rocket::response::Result<'r> { + let mut build = rocket::response::Response::build(); + build.status(match self.0 { + ErrorKind::FileNotFound => rocket::http::Status::NotFound, + _ => rocket::http::Status::InternalServerError, + }).ok() + } +} + impl From for IronError { fn from(err: Error) -> IronError { match err { diff --git a/src/rocket_api.rs b/src/rocket_api.rs index 883bbff..f0f923a 100644 --- a/src/rocket_api.rs +++ b/src/rocket_api.rs @@ -1,20 +1,28 @@ use rocket::http::{Cookie, Cookies, Status}; use rocket::request::{self, FromRequest, Request}; +use rocket::response::NamedFile; use rocket::{Outcome, State}; use rocket_contrib::json::Json; use std::path::PathBuf; +use std::ops::Deref; use std::sync::Arc; use config::{self, Config}; use db::DB; use errors; use index; +use thumbnails; use user; +use utils; +use vfs::VFSSource; const CURRENT_MAJOR_VERSION: i32 = 2; const CURRENT_MINOR_VERSION: i32 = 2; const SESSION_FIELD_USERNAME: &str = "username"; +// TODO every path.. argument breaks when the path contains square brackets. Needs URLencoding back!! +// TODO range header not supported + pub fn get_routes() -> Vec { routes![ version, @@ -31,6 +39,7 @@ pub fn get_routes() -> Vec { recent, search_root, search, + serve, ] } @@ -145,7 +154,7 @@ fn auth( db: State, credentials: Json, mut cookies: Cookies, -) -> Result<(Json), errors::Error> { +) -> Result, errors::Error> { user::auth::(&db, &credentials.username, &credentials.password)?; cookies.add_private(Cookie::new( SESSION_FIELD_USERNAME, @@ -162,7 +171,7 @@ fn auth( fn browse_root( db: State, _auth: Auth, -) -> Result<(Json>), errors::Error> { +) -> Result>, errors::Error> { let result = index::browse::(&db, &PathBuf::new())?; Ok(Json(result)) } @@ -172,13 +181,13 @@ fn browse( db: State, _auth: Auth, path: PathBuf, -) -> Result<(Json>), errors::Error> { +) -> Result>, errors::Error> { let result = index::browse::(&db, &path)?; Ok(Json(result)) } #[get("/flatten")] -fn flatten_root(db: State, _auth: Auth) -> Result<(Json>), errors::Error> { +fn flatten_root(db: State, _auth: Auth) -> Result>, errors::Error> { let result = index::flatten::(&db, &PathBuf::new())?; Ok(Json(result)) } @@ -188,31 +197,47 @@ fn flatten( db: State, _auth: Auth, path: PathBuf, -) -> Result<(Json>), errors::Error> { +) -> Result>, errors::Error> { let result = index::flatten::(&db, &path)?; Ok(Json(result)) } #[get("/random")] -fn random(db: State, _auth: Auth) -> Result<(Json>), errors::Error> { +fn random(db: State, _auth: Auth) -> Result>, errors::Error> { let result = index::get_random_albums::(&db, 20)?; Ok(Json(result)) } #[get("/recent")] -fn recent(db: State, _auth: Auth) -> Result<(Json>), errors::Error> { +fn recent(db: State, _auth: Auth) -> Result>, errors::Error> { let result = index::get_recent_albums::(&db, 20)?; Ok(Json(result)) } #[get("/search")] -fn search_root(db: State, _auth: Auth) -> Result<(Json>), errors::Error> { +fn search_root(db: State, _auth: Auth) -> Result>, errors::Error> { let result = index::search::(&db, "")?; Ok(Json(result)) } #[get("/search/")] -fn search(db: State, _auth: Auth, query: String) -> Result<(Json>), errors::Error> { +fn search(db: State, _auth: Auth, query: String) -> Result>, errors::Error> { let result = index::search::(&db, &query)?; Ok(Json(result)) } + +#[get("/serve/")] +fn serve(db: State, _auth: Auth, path: PathBuf) -> Result { + let db: &DB = db.deref(); + let vfs = db.get_vfs()?; + let real_path = vfs.virtual_to_real(&path)?; + + let serve_path = if utils::is_image(&real_path) { + thumbnails::get_thumbnail(&real_path, 400)? + } else { + real_path + }; + + let serving = NamedFile::open(&serve_path)?; + Ok(serving) +}