mirror of
https://github.com/amigan/rustypaste-pretty.git
synced 2024-11-21 20:09:48 -05:00
feat(paste): support overriding MIME types
This commit is contained in:
parent
0296bc0594
commit
03348cb38f
7 changed files with 119 additions and 0 deletions
13
Cargo.lock
generated
13
Cargo.lock
generated
|
@ -1520,9 +1520,12 @@ dependencies = [
|
|||
"futures-util",
|
||||
"infer",
|
||||
"log",
|
||||
"mime",
|
||||
"petname",
|
||||
"rand 0.8.4",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_regex",
|
||||
"url",
|
||||
]
|
||||
|
||||
|
@ -1602,6 +1605,16 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_regex"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8136f1a4ea815d7eac4101cfd0b16dc0cb5e1fe1b8609dfd728058656b7badf"
|
||||
dependencies = [
|
||||
"regex",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_urlencoded"
|
||||
version = "0.7.0"
|
||||
|
|
|
@ -24,6 +24,9 @@ petname = "1.1.0"
|
|||
rand = "0.8.4"
|
||||
dotenv = "0.15.0"
|
||||
url = "2.2.2"
|
||||
mime = "0.3.16"
|
||||
regex = "1.5.4"
|
||||
serde_regex = "1.1.0"
|
||||
|
||||
[dependencies.config]
|
||||
version = "0.11.0"
|
||||
|
|
|
@ -8,3 +8,12 @@ upload_path="./upload"
|
|||
random_url = { enabled = true, type = "petname", words = 2, separator = "-" }
|
||||
#random_url = { enabled = true, type = "alphanumeric", length = 8 }
|
||||
default_extension = "txt"
|
||||
mime_override = [
|
||||
{ mime = "image/jpeg", regex = "^.*\\.jpg$" },
|
||||
{ mime = "image/png", regex = "^.*\\.png$" },
|
||||
{ mime = "image/svg+xml", regex = "^.*\\.svg$" },
|
||||
{ mime = "video/webm", regex = "^.*\\.webm$" },
|
||||
{ mime = "video/x-matroska", regex = "^.*\\.mkv$" },
|
||||
{ mime = "application/octet-stream", regex = "^.*\\.bin$" },
|
||||
{ mime = "text/plain", regex = "^.*\\.(log|txt|diff)$" },
|
||||
]
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::mime::MimeMatcher;
|
||||
use crate::random::RandomURLConfig;
|
||||
use byte_unit::Byte;
|
||||
use config::{self, ConfigError};
|
||||
|
@ -32,6 +33,8 @@ pub struct PasteConfig {
|
|||
pub random_url: RandomURLConfig,
|
||||
/// Default file extension.
|
||||
pub default_extension: String,
|
||||
/// Media type override options.
|
||||
pub mime_override: Vec<MimeMatcher>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
|
|
|
@ -18,3 +18,6 @@ pub mod auth;
|
|||
|
||||
/// Storage handler.
|
||||
pub mod paste;
|
||||
|
||||
/// Media type handler.
|
||||
pub mod mime;
|
||||
|
|
83
src/mime.rs
Normal file
83
src/mime.rs
Normal file
|
@ -0,0 +1,83 @@
|
|||
use actix_files::file_extension_to_mime;
|
||||
use mime::{FromStrError, Mime};
|
||||
use regex::Regex;
|
||||
use std::path::PathBuf;
|
||||
use std::str::FromStr;
|
||||
|
||||
/// Matcher for MIME types.
|
||||
#[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub struct MimeMatcher {
|
||||
/// MIME type to set for the matched file name.
|
||||
pub mime: String,
|
||||
/// Regex for matching the file name.
|
||||
#[serde(with = "serde_regex")]
|
||||
pub regex: Option<Regex>,
|
||||
}
|
||||
|
||||
/// Returns the appropriate media type using an array of
|
||||
/// [`MIME matcher`]s and the file name.
|
||||
///
|
||||
/// [`MIME matcher`]: MimeMatcher
|
||||
pub fn get_mime_type(
|
||||
mime_matchers: &[MimeMatcher],
|
||||
file_name: String,
|
||||
) -> Result<Mime, FromStrError> {
|
||||
let path = PathBuf::from(&file_name);
|
||||
let mut mime_type = file_extension_to_mime(
|
||||
path.extension()
|
||||
.map(|v| v.to_str())
|
||||
.flatten()
|
||||
.unwrap_or_default(),
|
||||
);
|
||||
for matcher in mime_matchers {
|
||||
if matcher
|
||||
.regex
|
||||
.as_ref()
|
||||
.map(|r| r.is_match(&file_name))
|
||||
.unwrap_or(false)
|
||||
{
|
||||
mime_type = Mime::from_str(&matcher.mime)?;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Ok(mime_type)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_match_mime_type() {
|
||||
assert_eq!(
|
||||
mime::TEXT_PLAIN,
|
||||
get_mime_type(
|
||||
&[MimeMatcher {
|
||||
mime: String::from("text/plain"),
|
||||
regex: Regex::new("^.*\\.test$").ok(),
|
||||
}],
|
||||
String::from("mime.test")
|
||||
)
|
||||
.unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
mime::IMAGE_PNG,
|
||||
get_mime_type(
|
||||
&[MimeMatcher {
|
||||
mime: String::from("image/png"),
|
||||
regex: Regex::new("^.*\\.PNG$").ok(),
|
||||
}],
|
||||
String::from("image.PNG")
|
||||
)
|
||||
.unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
mime::APPLICATION_PDF,
|
||||
get_mime_type(&[], String::from("book.pdf")).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
mime::APPLICATION_OCTET_STREAM,
|
||||
get_mime_type(&[], String::from("x.unknown")).unwrap()
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
use crate::auth;
|
||||
use crate::config::Config;
|
||||
use crate::header::ContentDisposition;
|
||||
use crate::mime;
|
||||
use crate::paste::{Paste, PasteType};
|
||||
use actix_files::NamedFile;
|
||||
use actix_multipart::Multipart;
|
||||
|
@ -38,6 +39,10 @@ async fn serve(
|
|||
match paste_type {
|
||||
PasteType::File => Ok(NamedFile::open(&path)?
|
||||
.disable_content_disposition()
|
||||
.set_content_type(
|
||||
mime::get_mime_type(&config.paste.mime_override, file.to_string())
|
||||
.map_err(error::ErrorInternalServerError)?,
|
||||
)
|
||||
.prefer_utf8(true)
|
||||
.into_response(&request)?),
|
||||
PasteType::Url => Ok(HttpResponse::Found()
|
||||
|
|
Loading…
Reference in a new issue