Update S3 features and make S3 support optional

This commit is contained in:
Alex Auvolat 2023-05-12 12:28:00 +02:00
parent 10e06737cf
commit 1cb9459a23
5 changed files with 71 additions and 53 deletions

View File

@ -19,7 +19,6 @@ rocket = "0.4.11"
rocket_contrib = { version = "0.4.11", features = ["json"] } rocket_contrib = { version = "0.4.11", features = ["json"] }
rocket_i18n = "0.4.1" rocket_i18n = "0.4.1"
scheduled-thread-pool = "0.2.6" scheduled-thread-pool = "0.2.6"
#aws-creds = { version = "0.34", default-features = false, features = ["native-tls"] }
serde = "1.0.137" serde = "1.0.137"
serde_json = "1.0.81" serde_json = "1.0.81"
shrinkwraprs = "0.3.0" shrinkwraprs = "0.3.0"
@ -69,7 +68,7 @@ ructe = "0.15.0"
rsass = "0.26" rsass = "0.26"
[features] [features]
default = ["postgres", "s3"] default = ["postgres"]
postgres = ["plume-models/postgres", "diesel/postgres"] postgres = ["plume-models/postgres", "diesel/postgres"]
sqlite = ["plume-models/sqlite", "diesel/sqlite"] sqlite = ["plume-models/sqlite", "diesel/sqlite"]
debug-mailer = [] debug-mailer = []

View File

@ -18,7 +18,6 @@ rocket_i18n = "0.4.1"
reqwest = "0.11.11" reqwest = "0.11.11"
scheduled-thread-pool = "0.2.6" scheduled-thread-pool = "0.2.6"
serde = "1.0.137" serde = "1.0.137"
#rust-s3 = { version = "0.29.0", default-features = false, features = ["blocking"] }
rust-s3 = { version = "0.33.0", optional = true, features = ["blocking"] } rust-s3 = { version = "0.33.0", optional = true, features = ["blocking"] }
serde_derive = "1.0" serde_derive = "1.0"
serde_json = "1.0.81" serde_json = "1.0.81"

View File

@ -6,9 +6,8 @@ use rocket::Config as RocketConfig;
use std::collections::HashSet; use std::collections::HashSet;
use std::env::{self, var}; use std::env::{self, var};
use s3::{Bucket, Region}; #[cfg(feature = "s3")]
use s3::creds::Credentials; use s3::{Bucket, Region, creds::Credentials};
#[cfg(not(test))] #[cfg(not(test))]
const DB_NAME: &str = "plume"; const DB_NAME: &str = "plume";
@ -382,6 +381,7 @@ pub struct S3Config {
} }
impl S3Config { impl S3Config {
#[cfg(feature = "s3")]
pub fn get_bucket(&self) -> Bucket { pub fn get_bucket(&self) -> Bucket {
let region = Region::Custom { let region = Region::Custom {
region: self.region.clone(), region: self.region.clone(),
@ -411,6 +411,12 @@ fn get_s3_config() -> Option<S3Config> {
if bucket.is_none() && access_key_id.is_none() && access_key_secret.is_none() { if bucket.is_none() && access_key_id.is_none() && access_key_secret.is_none() {
return None; return None;
} }
#[cfg(not(feature = "s3"))]
panic!("S3 support is not enabled in this build");
#[cfg(feature = "s3")]
{
if bucket.is_none() || access_key_id.is_none() || access_key_secret.is_none() { if bucket.is_none() || access_key_id.is_none() || access_key_secret.is_none() {
panic!("Invalid S3 configuration: some required values are set, but not others"); panic!("Invalid S3 configuration: some required values are set, but not others");
} }
@ -434,6 +440,7 @@ fn get_s3_config() -> Option<S3Config> {
let direct_download = string_to_bool(&direct_download, "S3_DIRECT_DOWNLOAD"); let direct_download = string_to_bool(&direct_download, "S3_DIRECT_DOWNLOAD");
let alias = var("S3_ALIAS_HOST").ok(); let alias = var("S3_ALIAS_HOST").ok();
Some(S3Config { Some(S3Config {
bucket, bucket,
access_key_id, access_key_id,
@ -447,6 +454,7 @@ fn get_s3_config() -> Option<S3Config> {
alias, alias,
}) })
} }
}
lazy_static! { lazy_static! {
pub static ref CONFIG: Config = Config { pub static ref CONFIG: Config = Config {

View File

@ -170,9 +170,12 @@ impl Media {
pub fn delete(&self, conn: &Connection) -> Result<()> { pub fn delete(&self, conn: &Connection) -> Result<()> {
if !self.is_remote { if !self.is_remote {
if let Some(config) = &CONFIG.s3 { if CONFIG.s3.is_some() {
config.get_bucket() #[cfg(feature = "s3")]
CONFIG.s3.as_ref().unwrap().get_bucket()
.delete_object_blocking(&self.file_path)?; .delete_object_blocking(&self.file_path)?;
#[cfg(not(feature="s3"))]
unreachable!();
} else { } else {
fs::remove_file(self.file_path.as_str())?; fs::remove_file(self.file_path.as_str())?;
} }

View File

@ -9,7 +9,7 @@ use rocket::{
http::{ http::{
hyper::header::{CacheControl, CacheDirective, ETag, EntityTag}, hyper::header::{CacheControl, CacheDirective, ETag, EntityTag},
uri::{FromUriParam, Query}, uri::{FromUriParam, Query},
ContentType, RawStr, Status, RawStr, Status,
}, },
request::{self, FromFormValue, FromRequest, Request}, request::{self, FromFormValue, FromRequest, Request},
response::{self, Flash, NamedFile, Redirect, Responder, Response}, response::{self, Flash, NamedFile, Redirect, Responder, Response},
@ -21,6 +21,9 @@ use std::{
path::{Path, PathBuf}, path::{Path, PathBuf},
}; };
#[cfg(feature = "s3")]
use rocket::http::ContentType;
/// Special return type used for routes that "cannot fail", and instead /// Special return type used for routes that "cannot fail", and instead
/// `Redirect`, or `Flash<Redirect>`, when we cannot deliver a `Ructe` Response /// `Redirect`, or `Flash<Redirect>`, when we cannot deliver a `Ructe` Response
#[allow(clippy::large_enum_variant)] #[allow(clippy::large_enum_variant)]
@ -207,6 +210,7 @@ pub mod well_known;
#[derive(Responder)] #[derive(Responder)]
enum FileKind { enum FileKind {
Local(NamedFile), Local(NamedFile),
#[cfg(feature = "s3")]
S3(Vec<u8>, ContentType), S3(Vec<u8>, ContentType),
} }
@ -259,18 +263,23 @@ pub fn plume_static_files(file: PathBuf, build_id: &RawStr) -> Option<CachedFile
} }
#[get("/static/media/<file..>")] #[get("/static/media/<file..>")]
pub fn plume_media_files(file: PathBuf) -> Option<CachedFile> { pub fn plume_media_files(file: PathBuf) -> Option<CachedFile> {
if let Some(config) = &CONFIG.s3 { if CONFIG.s3.is_some() {
#[cfg(feature="s3")]
{
let ct = file.extension() let ct = file.extension()
.and_then(|ext| ContentType::from_extension(&ext.to_string_lossy())) .and_then(|ext| ContentType::from_extension(&ext.to_string_lossy()))
.unwrap_or(ContentType::Binary); .unwrap_or(ContentType::Binary);
let data = config.get_bucket() let data = CONFIG.s3.as_ref().unwrap().get_bucket()
.get_object_blocking(format!("plume-media/{}", file.to_string_lossy())).ok()?; .get_object_blocking(format!("plume-media/{}", file.to_string_lossy())).ok()?;
Some(CachedFile { Some(CachedFile {
inner: FileKind::S3 ( data.to_vec(), ct), inner: FileKind::S3 ( data.to_vec(), ct),
cache_control: CacheControl(vec![CacheDirective::MaxAge(60 * 60 * 24 * 30)]), cache_control: CacheControl(vec![CacheDirective::MaxAge(60 * 60 * 24 * 30)]),
}) })
}
#[cfg(not(feature="s3"))]
unreachable!();
} else { } else {
NamedFile::open(Path::new(&CONFIG.media_directory).join(file)) NamedFile::open(Path::new(&CONFIG.media_directory).join(file))
.ok() .ok()