Thumbnail and audio endpoints no longer encode payloads
This commit is contained in:
parent
f27bc4ccfc
commit
39c8cf7595
3 changed files with 70 additions and 9 deletions
|
@ -2,17 +2,17 @@ use actix_files::NamedFile;
|
|||
use actix_web::{
|
||||
client::HttpError,
|
||||
delete,
|
||||
dev::{MessageBody, Payload, Service, ServiceRequest, ServiceResponse},
|
||||
dev::{BodyEncoding, MessageBody, Payload, Service, ServiceRequest, ServiceResponse},
|
||||
error::{BlockingError, ErrorForbidden, ErrorInternalServerError, ErrorUnauthorized},
|
||||
get,
|
||||
http::StatusCode,
|
||||
http::{ContentEncoding, StatusCode},
|
||||
post, put,
|
||||
web::{self, Data, Json, JsonConfig, ServiceConfig},
|
||||
FromRequest, HttpMessage, HttpRequest, HttpResponse, ResponseError,
|
||||
FromRequest, HttpMessage, HttpRequest, HttpResponse, Responder, ResponseError,
|
||||
};
|
||||
use actix_web_httpauth::extractors::{basic::BasicAuth, bearer::BearerAuth};
|
||||
use cookie::{self, *};
|
||||
use futures_util::future::{err, ok};
|
||||
use futures_util::future::{err, ok, ready, Ready};
|
||||
use percent_encoding::percent_decode_str;
|
||||
use std::future::Future;
|
||||
use std::ops::Deref;
|
||||
|
@ -378,6 +378,34 @@ fn add_auth_cookies<T>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
struct MediaFile {
|
||||
named_file: NamedFile,
|
||||
}
|
||||
|
||||
impl MediaFile {
|
||||
fn new(named_file: NamedFile) -> Self {
|
||||
Self {
|
||||
named_file: named_file,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Responder for MediaFile {
|
||||
type Error = actix_web::Error;
|
||||
type Future = Ready<Result<HttpResponse, actix_web::Error>>;
|
||||
|
||||
fn respond_to(self, req: &HttpRequest) -> Self::Future {
|
||||
let mut response = self.named_file.into_response(req);
|
||||
if let Ok(r) = response.as_mut() {
|
||||
// Intentionally turn off content encoding for media files because:
|
||||
// 1. There is little value in compressing files that are already compressed (mp3, jpg, etc.)
|
||||
// 2. The Content-Length header is incompatible with content encoding (other than identity), and can be valuable for clients
|
||||
r.encoding(ContentEncoding::Identity);
|
||||
}
|
||||
return ready(response);
|
||||
}
|
||||
}
|
||||
|
||||
async fn block<F, I, E>(f: F) -> Result<I, APIError>
|
||||
where
|
||||
F: FnOnce() -> Result<I, E> + Send + 'static,
|
||||
|
@ -681,7 +709,7 @@ async fn get_audio(
|
|||
vfs_manager: Data<vfs::Manager>,
|
||||
_auth: Auth,
|
||||
path: web::Path<String>,
|
||||
) -> Result<NamedFile, APIError> {
|
||||
) -> Result<MediaFile, APIError> {
|
||||
let audio_path = block(move || {
|
||||
let vfs = vfs_manager.get_vfs()?;
|
||||
let path = percent_decode_str(&(path.0)).decode_utf8_lossy();
|
||||
|
@ -691,7 +719,7 @@ async fn get_audio(
|
|||
.await?;
|
||||
|
||||
let named_file = NamedFile::open(&audio_path).map_err(|_| APIError::AudioFileIOError)?;
|
||||
Ok(named_file)
|
||||
Ok(MediaFile::new(named_file))
|
||||
}
|
||||
|
||||
#[get("/thumbnail/{path:.*}")]
|
||||
|
@ -701,7 +729,7 @@ async fn get_thumbnail(
|
|||
_auth: Auth,
|
||||
path: web::Path<String>,
|
||||
options_input: web::Query<dto::ThumbnailOptions>,
|
||||
) -> Result<NamedFile, APIError> {
|
||||
) -> Result<MediaFile, APIError> {
|
||||
let options = thumbnail::Options::from(options_input.0);
|
||||
|
||||
let thumbnail_path = block(move || {
|
||||
|
@ -719,7 +747,7 @@ async fn get_thumbnail(
|
|||
let named_file =
|
||||
NamedFile::open(&thumbnail_path).map_err(|_| APIError::ThumbnailFileIOError)?;
|
||||
|
||||
Ok(named_file)
|
||||
Ok(MediaFile::new(named_file))
|
||||
}
|
||||
|
||||
#[get("/playlists")]
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::app::{config, ddns, settings, thumbnail, user, vfs};
|
|||
use std::convert::From;
|
||||
|
||||
pub const API_MAJOR_VERSION: i32 = 6;
|
||||
pub const API_MINOR_VERSION: i32 = 0;
|
||||
pub const API_MINOR_VERSION: i32 = 1;
|
||||
pub const COOKIE_SESSION: &str = "session";
|
||||
pub const COOKIE_USERNAME: &str = "username";
|
||||
pub const COOKIE_ADMIN: &str = "admin";
|
||||
|
|
|
@ -34,6 +34,39 @@ fn audio_golden_path() {
|
|||
let response = service.fetch_bytes(&request);
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
assert_eq!(response.body().len(), 24_142);
|
||||
assert_eq!(
|
||||
response.headers().get(header::CONTENT_LENGTH).unwrap(),
|
||||
"24142"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn audio_does_not_encode_content() {
|
||||
let mut service = ServiceType::new(&test_name!());
|
||||
service.complete_initial_setup();
|
||||
service.login_admin();
|
||||
service.index();
|
||||
service.login();
|
||||
|
||||
let path: PathBuf = [TEST_MOUNT_NAME, "Khemmis", "Hunted", "02 - Candlelight.mp3"]
|
||||
.iter()
|
||||
.collect();
|
||||
|
||||
let mut request = protocol::audio(&path);
|
||||
let headers = request.headers_mut();
|
||||
headers.append(
|
||||
header::ACCEPT_ENCODING,
|
||||
HeaderValue::from_str("gzip, deflate, br").unwrap(),
|
||||
);
|
||||
|
||||
let response = service.fetch_bytes(&request);
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
assert_eq!(response.body().len(), 24_142);
|
||||
assert_eq!(response.headers().get(header::TRANSFER_ENCODING), None);
|
||||
assert_eq!(
|
||||
response.headers().get(header::CONTENT_LENGTH).unwrap(),
|
||||
"24142"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Add table
Reference in a new issue