68 lines
2.2 KiB
Rust
68 lines
2.2 KiB
Rust
use crate::controllers::HttpResult;
|
|
use crate::extractors::matrix_client_extractor::MatrixClientExtractor;
|
|
use crate::utils::crypt_utils::sha512;
|
|
use actix_web::dev::Payload;
|
|
use actix_web::http::header;
|
|
use actix_web::{FromRequest, HttpRequest, HttpResponse, web};
|
|
use matrix_sdk::media::{MediaFormat, MediaRequestParameters, MediaThumbnailSettings};
|
|
use matrix_sdk::ruma::events::room::MediaSource;
|
|
use matrix_sdk::ruma::{OwnedMxcUri, UInt};
|
|
|
|
#[derive(serde::Deserialize)]
|
|
struct MediaQuery {
|
|
#[serde(default)]
|
|
thumbnail: bool,
|
|
}
|
|
|
|
/// Serve a media file
|
|
pub async fn serve_media(req: HttpRequest, media: OwnedMxcUri) -> HttpResult {
|
|
let query = web::Query::<MediaQuery>::from_request(&req, &mut Payload::None).await?;
|
|
let client = MatrixClientExtractor::from_request(&req, &mut Payload::None).await?;
|
|
|
|
let media = client
|
|
.client
|
|
.client
|
|
.media()
|
|
.get_media_content(
|
|
&MediaRequestParameters {
|
|
source: MediaSource::Plain(media),
|
|
format: match query.thumbnail {
|
|
true => MediaFormat::Thumbnail(MediaThumbnailSettings::new(
|
|
UInt::new(100).unwrap(),
|
|
UInt::new(100).unwrap(),
|
|
)),
|
|
false => MediaFormat::File,
|
|
},
|
|
},
|
|
true,
|
|
)
|
|
.await?;
|
|
|
|
let digest = sha512(&media);
|
|
|
|
let mime_type = infer::get(&media).map(|x| x.mime_type());
|
|
|
|
// Check if the browser already knows the etag
|
|
if let Some(c) = req.headers().get(header::IF_NONE_MATCH)
|
|
&& c.to_str().unwrap_or("") == digest
|
|
{
|
|
return Ok(HttpResponse::NotModified().finish());
|
|
}
|
|
|
|
Ok(HttpResponse::Ok()
|
|
.content_type(mime_type.unwrap_or("application/octet-stream"))
|
|
.insert_header(("etag", digest))
|
|
.insert_header(("cache-control", "max-age=360000"))
|
|
.body(media))
|
|
}
|
|
|
|
#[derive(serde::Deserialize)]
|
|
pub struct MediaMXCInPath {
|
|
mxc: OwnedMxcUri,
|
|
}
|
|
|
|
/// Save media resource handler
|
|
pub async fn serve_media_res(req: HttpRequest, media: web::Path<MediaMXCInPath>) -> HttpResult {
|
|
serve_media(req, media.into_inner().mxc).await
|
|
}
|