Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,8 @@ license = "MIT"
readme = "README.md"

[features]
default = ["dimse", "s3"]
dimse = []
# TODO: feature-gate S3 dependencies
s3 = []
default = []
s3 = ["dep:aws-config", "dep:aws-sdk-s3", "dep:aws-credential-types"]

[dependencies]
# DICOM processing
Expand Down Expand Up @@ -54,9 +52,9 @@ multer = "3.1.0"
pin-project = "1.1.10"
image = { version = "0.25.6", features = ["png", "jpeg", "gif"] }
# S3 backend
aws-config = { version = "1.6.2", features = ["behavior-version-latest"] }
aws-sdk-s3 = "1.85.0"
aws-credential-types = "1.2.3"
aws-config = { version = "1.6.2", features = ["behavior-version-latest"], optional = true }
aws-sdk-s3 = { version = "1.85.0", optional = true }
aws-credential-types = { version = "1.2.3", optional = true }

[lints.rust]
unsafe_code = "forbid"
Expand Down
34 changes: 14 additions & 20 deletions src/backend/mod.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
use crate::api::qido::QidoService;
use crate::api::stow::StowService;
use crate::api::wado::WadoService;
use crate::backend::dimse::qido::DimseQidoService;
use crate::backend::dimse::stow::DimseStowService;
use crate::backend::dimse::wado::DimseWadoService;
use crate::backend::s3::wado::S3WadoService;
use crate::config::BackendConfig;
use crate::AppState;
use async_trait::async_trait;
use axum::extract::{FromRef, FromRequestParts, Path};
use axum::http::request::Parts;
use axum::http::StatusCode;
use serde::Deserialize;
use std::time::Duration;

// #[cfg(feature = "dimse")]
pub mod dimse;

#[cfg(feature = "s3")]
Expand Down Expand Up @@ -54,8 +48,11 @@ where

// TODO: Use a singleton to avoid re-creating on every request.
let provider = match ae_config.backend {
#[cfg(feature = "dimse")]
BackendConfig::Dimse { .. } => {
use crate::backend::dimse::qido::DimseQidoService;
use crate::backend::dimse::stow::DimseStowService;
use crate::backend::dimse::wado::DimseWadoService;

let pool = state.pools.get(&ae_config.aet).expect("pool should exist");

Self {
Expand All @@ -75,19 +72,16 @@ where
))),
}
}
// For some reason serde doesn't work with feature-gated enum variants.
// A no-op backend is used as a workaround if the dimse feature is not enabled.
#[cfg(not(feature = "dimse"))]
Backend::Dimse => Self {
qido: None,
wado: None,
stow: None,
},
BackendConfig::S3(config) => Self {
qido: None,
wado: Some(Box::new(S3WadoService::new(&config))),
stow: None,
},
#[cfg(feature = "s3")]
BackendConfig::S3(config) => {
use crate::backend::s3::wado::S3WadoService;

Self {
qido: None,
wado: Some(Box::new(S3WadoService::new(&config))),
stow: None,
}
}
};

Ok(provider)
Expand Down
19 changes: 10 additions & 9 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::types::AE;
use crate::DEFAULT_AET;
use aws_credential_types::Credentials as AwsCredentials;

use serde::de::Error;
use serde::{Deserialize, Deserializer};
use std::net::IpAddr;
Expand Down Expand Up @@ -36,6 +36,7 @@ pub struct ApplicationEntityConfig {
pub enum BackendConfig {
#[serde(rename = "DIMSE")]
Dimse(DimseConfig),
#[cfg(feature = "s3")]
#[serde(rename = "S3")]
S3(S3Config),
}
Expand All @@ -49,6 +50,7 @@ pub struct DimseConfig {
pub pool: PoolConfig,
}

#[cfg(feature = "s3")]
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub struct S3Config {
Expand All @@ -63,19 +65,22 @@ pub struct S3Config {
pub endpoint_style: S3EndpointStyle,
}

#[cfg(feature = "s3")]
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum S3EndpointStyle {
Path,
VHost,
}

#[cfg(feature = "s3")]
impl Default for S3EndpointStyle {
fn default() -> Self {
Self::VHost
}
}

#[cfg(feature = "s3")]
#[derive(Debug, Clone, Deserialize)]
#[serde(untagged)]
pub enum S3CredentialsConfig {
Expand All @@ -91,13 +96,14 @@ pub enum S3CredentialsConfig {
},
}

#[cfg(feature = "s3")]
impl S3CredentialsConfig {
pub fn resolve(&self) -> Result<AwsCredentials, std::env::VarError> {
pub fn resolve(&self) -> Result<aws_credential_types::Credentials, std::env::VarError> {
match &self {
Self::Plain {
access_key,
secret_key,
} => Ok(AwsCredentials::new(
} => Ok(aws_credential_types::Credentials::new(
access_key,
secret_key,
None,
Expand All @@ -110,7 +116,7 @@ impl S3CredentialsConfig {
} => {
let access_key = std::env::var(access_key_env)?;
let secret_key = std::env::var(secret_key_env)?;
Ok(AwsCredentials::new(
Ok(aws_credential_types::Credentials::new(
access_key,
secret_key,
None,
Expand Down Expand Up @@ -274,14 +280,9 @@ pub enum Backend {
}

impl Default for Backend {
#[cfg(feature = "dimse")]
fn default() -> Self {
Self::Dimse
}
#[cfg(not(feature = "dimse"))]
fn default() -> Self {
Self::Disabled
}
}

impl Default for DimseServerConfig {
Expand Down
7 changes: 0 additions & 7 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,7 @@ fn init_logger(level: tracing::Level) {
#[derive(Clone)]
pub struct AppState {
pub config: AppConfig,
#[cfg(feature = "dimse")]
pub pools: AssociationPools,
#[cfg(feature = "dimse")]
pub mediator: MoveMediator,
}

Expand Down Expand Up @@ -102,20 +100,15 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
}

async fn run(config: AppConfig) -> anyhow::Result<()> {
#[cfg(feature = "dimse")]
let mediator = MoveMediator::new(&config);
#[cfg(feature = "dimse")]
let pools = AssociationPools::new(&config);

let app_state = AppState {
config: config.clone(),
#[cfg(feature = "dimse")]
mediator: mediator.clone(),
#[cfg(feature = "dimse")]
pools,
};

#[cfg(feature = "dimse")]
for dimse_config in config.server.dimse {
let mediator = mediator.clone();
let subscribers: Vec<AE> = config
Expand Down
Loading