diff --git a/router/src/handler.rs b/router/src/handler.rs deleted file mode 100644 index 64256d61a..000000000 --- a/router/src/handler.rs +++ /dev/null @@ -1 +0,0 @@ -pub trait Handler: Send + Sync + 'static {} diff --git a/router/src/handlers.rs b/router/src/handlers.rs new file mode 100644 index 000000000..5e4a0213d --- /dev/null +++ b/router/src/handlers.rs @@ -0,0 +1,181 @@ +use hyper::StatusCode; +use matchit::Params; +use s3s::{s3_error, Body, S3Request, S3Response, S3Result}; +use tracing::warn; + +use crate::router::Operation; + +pub struct AssumeRoleHandle {} +#[async_trait::async_trait] +impl Operation for AssumeRoleHandle { + async fn call(&self, _req: S3Request, _params: Params<'_, '_>) -> S3Result> { + warn!("handle AssumeRoleHandle"); + + return Err(s3_error!(NotImplemented)); + } +} + +pub struct ServiceHandle {} +#[async_trait::async_trait] +impl Operation for ServiceHandle { + async fn call(&self, _req: S3Request, _params: Params<'_, '_>) -> S3Result> { + warn!("handle ServiceHandle"); + + return Err(s3_error!(NotImplemented)); + } +} + +pub struct ServerInfoHandler {} + +#[async_trait::async_trait] +impl Operation for ServerInfoHandler { + async fn call(&self, _req: S3Request, _params: Params<'_, '_>) -> S3Result> { + warn!("handle ServerInfoHandler"); + + return Err(s3_error!(NotImplemented)); + } +} + +pub struct InspectDataHandler {} + +#[async_trait::async_trait] +impl Operation for InspectDataHandler { + async fn call(&self, _req: S3Request, _params: Params<'_, '_>) -> S3Result> { + warn!("handle InspectDataHandler"); + + return Err(s3_error!(NotImplemented)); + } +} + +pub struct StorageInfoHandler {} + +#[async_trait::async_trait] +impl Operation for StorageInfoHandler { + async fn call(&self, _req: S3Request, _params: Params<'_, '_>) -> S3Result> { + warn!("handle StorageInfoHandler"); + + return Err(s3_error!(NotImplemented)); + } +} + +pub struct DataUsageInfoHandler {} + +#[async_trait::async_trait] +impl Operation for DataUsageInfoHandler { + async fn call(&self, _req: S3Request, _params: Params<'_, '_>) -> S3Result> { + warn!("handle DataUsageInfoHandler"); + + return Err(s3_error!(NotImplemented)); + } +} + +pub struct MetricsHandler {} + +#[async_trait::async_trait] +impl Operation for MetricsHandler { + async fn call(&self, _req: S3Request, _params: Params<'_, '_>) -> S3Result> { + warn!("handle MetricsHandler"); + + return Err(s3_error!(NotImplemented)); + } +} + +pub struct HealHandler {} + +#[async_trait::async_trait] +impl Operation for HealHandler { + async fn call(&self, _req: S3Request, _params: Params<'_, '_>) -> S3Result> { + warn!("handle HealHandler"); + + return Err(s3_error!(NotImplemented)); + } +} + +pub struct BackgroundHealStatusHandler {} + +#[async_trait::async_trait] +impl Operation for BackgroundHealStatusHandler { + async fn call(&self, _req: S3Request, _params: Params<'_, '_>) -> S3Result> { + warn!("handle BackgroundHealStatusHandler"); + + return Err(s3_error!(NotImplemented)); + } +} + +pub struct ListPools {} + +#[async_trait::async_trait] +impl Operation for ListPools { + async fn call(&self, _req: S3Request, _params: Params<'_, '_>) -> S3Result> { + warn!("handle ListPools"); + + return Err(s3_error!(NotImplemented)); + } +} + +pub struct StatusPool {} + +#[async_trait::async_trait] +impl Operation for StatusPool { + async fn call(&self, _req: S3Request, _params: Params<'_, '_>) -> S3Result> { + warn!("handle StatusPool"); + + return Err(s3_error!(NotImplemented)); + } +} + +pub struct StartDecommission {} + +#[async_trait::async_trait] +impl Operation for StartDecommission { + async fn call(&self, _req: S3Request, _params: Params<'_, '_>) -> S3Result> { + warn!("handle StartDecommission"); + + return Err(s3_error!(NotImplemented)); + } +} + +pub struct CancelDecommission {} + +#[async_trait::async_trait] +impl Operation for CancelDecommission { + async fn call(&self, _req: S3Request, _params: Params<'_, '_>) -> S3Result> { + warn!("handle CancelDecommission"); + + return Err(s3_error!(NotImplemented)); + } +} + +pub struct RebalanceStart {} + +#[async_trait::async_trait] +impl Operation for RebalanceStart { + async fn call(&self, _req: S3Request, _params: Params<'_, '_>) -> S3Result> { + warn!("handle RebalanceStart"); + + return Err(s3_error!(NotImplemented)); + } +} + +// RebalanceStatus +pub struct RebalanceStatus {} + +#[async_trait::async_trait] +impl Operation for RebalanceStatus { + async fn call(&self, _req: S3Request, _params: Params<'_, '_>) -> S3Result> { + warn!("handle RebalanceStatus"); + + return Err(s3_error!(NotImplemented)); + } +} +// RebalanceStop +pub struct RebalanceStop {} + +#[async_trait::async_trait] +impl Operation for RebalanceStop { + async fn call(&self, _req: S3Request, _params: Params<'_, '_>) -> S3Result> { + warn!("handle RebalanceStop"); + + return Err(s3_error!(NotImplemented)); + } +} diff --git a/router/src/lib.rs b/router/src/lib.rs index 40f3f4be8..d111ad750 100644 --- a/router/src/lib.rs +++ b/router/src/lib.rs @@ -1,3 +1,101 @@ -pub mod handler; -pub mod operation; +pub mod handlers; pub mod router; + +use common::error::Result; +use hyper::Method; +use router::{AdminOperation, S3Router}; +use s3s::route::S3Route; + +const ADMIN_PREFIX: &str = "/rustfs/admin"; + +pub fn make_admin_route() -> Result { + let mut r = S3Router::new(); + + r.insert(Method::POST, "/", AdminOperation(&handlers::AssumeRoleHandle {}))?; + + r.insert( + Method::POST, + format!("{}{}", ADMIN_PREFIX, "/v3/service").as_str(), + AdminOperation(&handlers::ServiceHandle {}), + )?; + r.insert( + Method::GET, + format!("{}{}", ADMIN_PREFIX, "/v3/info").as_str(), + AdminOperation(&handlers::ServerInfoHandler {}), + )?; + r.insert( + Method::GET, + format!("{}{}", ADMIN_PREFIX, "/v3/inspect-data").as_str(), + AdminOperation(&handlers::InspectDataHandler {}), + )?; + r.insert( + Method::POST, + format!("{}{}", ADMIN_PREFIX, "/v3/inspect-data").as_str(), + AdminOperation(&handlers::InspectDataHandler {}), + )?; + r.insert( + Method::GET, + format!("{}{}", ADMIN_PREFIX, "/v3/storageinfo").as_str(), + AdminOperation(&handlers::StorageInfoHandler {}), + )?; + r.insert( + Method::GET, + format!("{}{}", ADMIN_PREFIX, "/v3/datausageinfo").as_str(), + AdminOperation(&handlers::DataUsageInfoHandler {}), + )?; + r.insert( + Method::GET, + format!("{}{}", ADMIN_PREFIX, "/v3/metrics").as_str(), + AdminOperation(&handlers::MetricsHandler {}), + )?; + + r.insert( + Method::POST, + format!("{}{}", ADMIN_PREFIX, "/v3/heal/{bucket}/{prefix}").as_str(), + AdminOperation(&handlers::HealHandler {}), + )?; + r.insert( + Method::POST, + format!("{}{}", ADMIN_PREFIX, "/v3/background-heal/status").as_str(), + AdminOperation(&handlers::BackgroundHealStatusHandler {}), + )?; + + r.insert( + Method::GET, + format!("{}{}", ADMIN_PREFIX, "/v3/pools/list").as_str(), + AdminOperation(&handlers::ListPools {}), + )?; + r.insert( + Method::GET, + format!("{}{}", ADMIN_PREFIX, "/v3/pools/status").as_str(), + AdminOperation(&handlers::StatusPool {}), + )?; + r.insert( + Method::POST, + format!("{}{}", ADMIN_PREFIX, "/v3/pools/decommission").as_str(), + AdminOperation(&handlers::StartDecommission {}), + )?; + r.insert( + Method::POST, + format!("{}{}", ADMIN_PREFIX, "/v3/pools/cancel").as_str(), + AdminOperation(&handlers::CancelDecommission {}), + )?; + + r.insert( + Method::POST, + format!("{}{}", ADMIN_PREFIX, "/v3/rebalance/start").as_str(), + AdminOperation(&handlers::RebalanceStart {}), + )?; + r.insert( + Method::GET, + format!("{}{}", ADMIN_PREFIX, "/v3/rebalance/status").as_str(), + AdminOperation(&handlers::RebalanceStatus {}), + )?; + r.insert( + Method::POST, + format!("{}{}", ADMIN_PREFIX, "/v3/rebalance/stop").as_str(), + AdminOperation(&handlers::RebalanceStop {}), + )?; + + Ok(r) +} diff --git a/router/src/operation.rs b/router/src/operation.rs deleted file mode 100644 index 6b3398520..000000000 --- a/router/src/operation.rs +++ /dev/null @@ -1,10 +0,0 @@ -use hyper::{Method, StatusCode}; -use matchit::Params; -use s3s::{Body, S3Request, S3Response, S3Result}; - -#[async_trait::async_trait] -pub trait Operation: Send + Sync + 'static { - fn method(&self) -> Method; - fn uri(&self) -> &'static str; - async fn call(&self, req: S3Request, params: Params<'_, '_>) -> S3Result>; -} diff --git a/router/src/router.rs b/router/src/router.rs index 2f137279b..11dbf19f1 100644 --- a/router/src/router.rs +++ b/router/src/router.rs @@ -1,26 +1,18 @@ -use std::collections::HashMap; -use std::str::FromStr; - +use common::error::Result; use hyper::http::Extensions; use hyper::HeaderMap; use hyper::Method; use hyper::StatusCode; use hyper::Uri; - +use matchit::Params; +use matchit::Router; +use s3s::header; use s3s::route::S3Route; use s3s::s3_error; use s3s::Body; use s3s::S3Request; use s3s::S3Response; use s3s::S3Result; -use tracing::warn; - -use crate::operation::Operation; -use common::error::Result; -use matchit::Router; - -const ADMIN_PREFIX: &str = "/rustfs/admin"; -// const ADMIN_VERSION: &str = "v3"; pub struct S3Router { router: Router, @@ -33,10 +25,10 @@ impl S3Router { Self { router } } - pub fn insert(&mut self, operation: T) -> Result<()> { - let path = Self::make_route_str(operation.method(), &operation.uri()); + pub fn insert(&mut self, method: Method, path: &str, operation: T) -> Result<()> { + let path = Self::make_route_str(method, path); - warn!("set uri {}", &path); + // warn!("set uri {}", &path); self.router.insert(path, operation)?; @@ -44,7 +36,13 @@ impl S3Router { } fn make_route_str(method: Method, path: &str) -> String { - format!("{}|{}{}", method.as_str(), ADMIN_PREFIX, path) + format!("{}|{}", method.as_str(), path) + } +} + +impl Default for S3Router { + fn default() -> Self { + Self::new() } } @@ -53,7 +51,16 @@ impl S3Route for S3Router where T: Operation, { - fn is_match(&self, _method: &Method, uri: &Uri, _headers: &HeaderMap, _: &mut Extensions) -> bool { + fn is_match(&self, method: &Method, uri: &Uri, headers: &HeaderMap, _: &mut Extensions) -> bool { + // AssumeRole + if method == Method::POST && uri.path() == "/" { + if let Some(val) = headers.get(header::CONTENT_TYPE) { + if val.as_bytes() == b"application/x-www-form-urlencoded" { + return true; + } + } + } + uri.path().starts_with("/rustfs/admin") } @@ -70,3 +77,19 @@ where return Err(s3_error!(NotImplemented)); } } + +#[async_trait::async_trait] +pub trait Operation: Send + Sync + 'static { + // fn method() -> Method; + // fn uri() -> &'static str; + async fn call(&self, req: S3Request, params: Params<'_, '_>) -> S3Result>; +} + +pub struct AdminOperation(pub &'static dyn Operation); + +#[async_trait::async_trait] +impl Operation for AdminOperation { + async fn call(&self, req: S3Request, params: Params<'_, '_>) -> S3Result> { + self.0.call(req, params).await + } +} diff --git a/rustfs/src/main.rs b/rustfs/src/main.rs index de4e7631c..46daded39 100644 --- a/rustfs/src/main.rs +++ b/rustfs/src/main.rs @@ -1,6 +1,5 @@ mod config; mod grpc; -mod route; mod service; mod storage; @@ -114,7 +113,7 @@ async fn run(opt: config::Opt) -> Result<()> { b.set_access(store.clone()); - b.set_route(route::make_admin_route()?); + b.set_route(router::make_admin_route()?); // // Enable parsing virtual-hosted-style requests // if let Some(dm) = opt.domain_name { diff --git a/rustfs/src/route.rs b/rustfs/src/route.rs deleted file mode 100644 index cba7a5efb..000000000 --- a/rustfs/src/route.rs +++ /dev/null @@ -1,68 +0,0 @@ -use common::error::{Error, Result}; - -use matchit::Params; -use router::{operation::Operation, router::S3Router}; -use s3s::route::S3Route; -use s3s::{Body, S3Request, S3Response, S3Result}; -use tracing::warn; - -use hyper::Method; -use hyper::StatusCode; - -pub fn make_admin_route() -> Result { - let mut r = S3Router::new(); - - r.insert(AdminOperation(&InfoHandler {}))?; - r.insert(AdminOperation(&ListPoolHandler {}))?; - - Ok(r) -} - -struct AdminOperation(&'static dyn Operation); - -#[async_trait::async_trait] -impl Operation for AdminOperation { - fn method(&self) -> Method { - self.0.method() - } - fn uri(&self) -> &'static str { - self.0.uri() - } - async fn call(&self, req: S3Request, params: Params<'_, '_>) -> S3Result> { - self.0.call(req, params).await - } -} - -struct InfoHandler {} - -#[async_trait::async_trait] -impl Operation for InfoHandler { - fn method(&self) -> Method { - Method::GET - } - fn uri(&self) -> &'static str { - "/v3/info" - } - async fn call(&self, _req: S3Request, _params: Params<'_, '_>) -> S3Result> { - warn!("handle info"); - - unimplemented!() - } -} - -struct ListPoolHandler {} - -#[async_trait::async_trait] -impl Operation for ListPoolHandler { - fn method(&self) -> Method { - Method::GET - } - fn uri(&self) -> &'static str { - "/v3/pool/list" - } - async fn call(&self, _req: S3Request, _params: Params<'_, '_>) -> S3Result> { - warn!("handle info"); - - unimplemented!() - } -}