forked from Deuxfleurs/garage
wip: split garage_api into garage_api_{common,s3,k2v,admin}
This commit is contained in:
parent
9330fd79d3
commit
9fa20d45be
52 changed files with 605 additions and 191 deletions
179
Cargo.lock
generated
179
Cargo.lock
generated
|
@ -1324,7 +1324,10 @@ dependencies = [
|
||||||
"format_table",
|
"format_table",
|
||||||
"futures",
|
"futures",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"garage_api",
|
"garage_api_admin",
|
||||||
|
"garage_api_common",
|
||||||
|
"garage_api_k2v",
|
||||||
|
"garage_api_s3",
|
||||||
"garage_block",
|
"garage_block",
|
||||||
"garage_db",
|
"garage_db",
|
||||||
"garage_model",
|
"garage_model",
|
||||||
|
@ -1365,7 +1368,7 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "garage_api"
|
name = "garage_api_admin"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes-gcm",
|
"aes-gcm",
|
||||||
|
@ -1382,6 +1385,175 @@ dependencies = [
|
||||||
"form_urlencoded",
|
"form_urlencoded",
|
||||||
"futures",
|
"futures",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
"garage_api_common",
|
||||||
|
"garage_block",
|
||||||
|
"garage_model",
|
||||||
|
"garage_net",
|
||||||
|
"garage_rpc",
|
||||||
|
"garage_table",
|
||||||
|
"garage_util",
|
||||||
|
"hex",
|
||||||
|
"hmac",
|
||||||
|
"http 1.0.0",
|
||||||
|
"http-body-util",
|
||||||
|
"http-range",
|
||||||
|
"httpdate",
|
||||||
|
"hyper 1.1.0",
|
||||||
|
"hyper-util",
|
||||||
|
"idna",
|
||||||
|
"md-5",
|
||||||
|
"multer",
|
||||||
|
"nom",
|
||||||
|
"opentelemetry",
|
||||||
|
"opentelemetry-prometheus",
|
||||||
|
"percent-encoding",
|
||||||
|
"pin-project",
|
||||||
|
"prometheus",
|
||||||
|
"quick-xml",
|
||||||
|
"roxmltree",
|
||||||
|
"serde",
|
||||||
|
"serde_bytes",
|
||||||
|
"serde_json",
|
||||||
|
"sha1",
|
||||||
|
"sha2",
|
||||||
|
"tokio",
|
||||||
|
"tokio-stream",
|
||||||
|
"tokio-util 0.7.10",
|
||||||
|
"tracing",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "garage_api_common"
|
||||||
|
version = "1.0.1"
|
||||||
|
dependencies = [
|
||||||
|
"aes-gcm",
|
||||||
|
"argon2",
|
||||||
|
"async-compression",
|
||||||
|
"async-trait",
|
||||||
|
"base64 0.21.7",
|
||||||
|
"bytes",
|
||||||
|
"chrono",
|
||||||
|
"crc32c",
|
||||||
|
"crc32fast",
|
||||||
|
"crypto-common",
|
||||||
|
"err-derive",
|
||||||
|
"form_urlencoded",
|
||||||
|
"futures",
|
||||||
|
"futures-util",
|
||||||
|
"garage_block",
|
||||||
|
"garage_model",
|
||||||
|
"garage_net",
|
||||||
|
"garage_rpc",
|
||||||
|
"garage_table",
|
||||||
|
"garage_util",
|
||||||
|
"hex",
|
||||||
|
"hmac",
|
||||||
|
"http 1.0.0",
|
||||||
|
"http-body-util",
|
||||||
|
"http-range",
|
||||||
|
"httpdate",
|
||||||
|
"hyper 1.1.0",
|
||||||
|
"hyper-util",
|
||||||
|
"idna",
|
||||||
|
"md-5",
|
||||||
|
"multer",
|
||||||
|
"nom",
|
||||||
|
"opentelemetry",
|
||||||
|
"opentelemetry-prometheus",
|
||||||
|
"percent-encoding",
|
||||||
|
"pin-project",
|
||||||
|
"prometheus",
|
||||||
|
"quick-xml",
|
||||||
|
"roxmltree",
|
||||||
|
"serde",
|
||||||
|
"serde_bytes",
|
||||||
|
"serde_json",
|
||||||
|
"sha1",
|
||||||
|
"sha2",
|
||||||
|
"tokio",
|
||||||
|
"tokio-stream",
|
||||||
|
"tokio-util 0.7.10",
|
||||||
|
"tracing",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "garage_api_k2v"
|
||||||
|
version = "1.0.1"
|
||||||
|
dependencies = [
|
||||||
|
"aes-gcm",
|
||||||
|
"argon2",
|
||||||
|
"async-compression",
|
||||||
|
"async-trait",
|
||||||
|
"base64 0.21.7",
|
||||||
|
"bytes",
|
||||||
|
"chrono",
|
||||||
|
"crc32c",
|
||||||
|
"crc32fast",
|
||||||
|
"crypto-common",
|
||||||
|
"err-derive",
|
||||||
|
"form_urlencoded",
|
||||||
|
"futures",
|
||||||
|
"futures-util",
|
||||||
|
"garage_api_common",
|
||||||
|
"garage_api_s3",
|
||||||
|
"garage_block",
|
||||||
|
"garage_model",
|
||||||
|
"garage_net",
|
||||||
|
"garage_rpc",
|
||||||
|
"garage_table",
|
||||||
|
"garage_util",
|
||||||
|
"hex",
|
||||||
|
"hmac",
|
||||||
|
"http 1.0.0",
|
||||||
|
"http-body-util",
|
||||||
|
"http-range",
|
||||||
|
"httpdate",
|
||||||
|
"hyper 1.1.0",
|
||||||
|
"hyper-util",
|
||||||
|
"idna",
|
||||||
|
"md-5",
|
||||||
|
"multer",
|
||||||
|
"nom",
|
||||||
|
"opentelemetry",
|
||||||
|
"opentelemetry-prometheus",
|
||||||
|
"percent-encoding",
|
||||||
|
"pin-project",
|
||||||
|
"prometheus",
|
||||||
|
"quick-xml",
|
||||||
|
"roxmltree",
|
||||||
|
"serde",
|
||||||
|
"serde_bytes",
|
||||||
|
"serde_json",
|
||||||
|
"sha1",
|
||||||
|
"sha2",
|
||||||
|
"tokio",
|
||||||
|
"tokio-stream",
|
||||||
|
"tokio-util 0.7.10",
|
||||||
|
"tracing",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "garage_api_s3"
|
||||||
|
version = "1.0.1"
|
||||||
|
dependencies = [
|
||||||
|
"aes-gcm",
|
||||||
|
"argon2",
|
||||||
|
"async-compression",
|
||||||
|
"async-trait",
|
||||||
|
"base64 0.21.7",
|
||||||
|
"bytes",
|
||||||
|
"chrono",
|
||||||
|
"crc32c",
|
||||||
|
"crc32fast",
|
||||||
|
"crypto-common",
|
||||||
|
"err-derive",
|
||||||
|
"form_urlencoded",
|
||||||
|
"futures",
|
||||||
|
"futures-util",
|
||||||
|
"garage_api_common",
|
||||||
"garage_block",
|
"garage_block",
|
||||||
"garage_model",
|
"garage_model",
|
||||||
"garage_net",
|
"garage_net",
|
||||||
|
@ -1614,7 +1786,8 @@ version = "1.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"err-derive",
|
"err-derive",
|
||||||
"futures",
|
"futures",
|
||||||
"garage_api",
|
"garage_api_common",
|
||||||
|
"garage_api_s3",
|
||||||
"garage_model",
|
"garage_model",
|
||||||
"garage_table",
|
"garage_table",
|
||||||
"garage_util",
|
"garage_util",
|
||||||
|
|
10
Cargo.toml
10
Cargo.toml
|
@ -8,7 +8,10 @@ members = [
|
||||||
"src/table",
|
"src/table",
|
||||||
"src/block",
|
"src/block",
|
||||||
"src/model",
|
"src/model",
|
||||||
"src/api",
|
"src/api/common",
|
||||||
|
"src/api/s3",
|
||||||
|
"src/api/k2v",
|
||||||
|
"src/api/admin",
|
||||||
"src/web",
|
"src/web",
|
||||||
"src/garage",
|
"src/garage",
|
||||||
"src/k2v-client",
|
"src/k2v-client",
|
||||||
|
@ -21,7 +24,10 @@ default-members = ["src/garage"]
|
||||||
|
|
||||||
# Internal Garage crates
|
# Internal Garage crates
|
||||||
format_table = { version = "0.1.1", path = "src/format-table" }
|
format_table = { version = "0.1.1", path = "src/format-table" }
|
||||||
garage_api = { version = "1.0.1", path = "src/api" }
|
garage_api_common = { version = "1.0.1", path = "src/api/common" }
|
||||||
|
garage_api_admin = { version = "1.0.1", path = "src/api/admin" }
|
||||||
|
garage_api_s3 = { version = "1.0.1", path = "src/api/s3" }
|
||||||
|
garage_api_k2v = { version = "1.0.1", path = "src/api/k2v" }
|
||||||
garage_block = { version = "1.0.1", path = "src/block" }
|
garage_block = { version = "1.0.1", path = "src/block" }
|
||||||
garage_db = { version = "1.0.1", path = "src/db", default-features = false }
|
garage_db = { version = "1.0.1", path = "src/db", default-features = false }
|
||||||
garage_model = { version = "1.0.1", path = "src/model", default-features = false }
|
garage_model = { version = "1.0.1", path = "src/model", default-features = false }
|
||||||
|
|
71
src/api/admin/Cargo.toml
Normal file
71
src/api/admin/Cargo.toml
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
[package]
|
||||||
|
name = "garage_api_admin"
|
||||||
|
version = "1.0.1"
|
||||||
|
authors = ["Alex Auvolat <alex@adnab.me>"]
|
||||||
|
edition = "2018"
|
||||||
|
license = "AGPL-3.0"
|
||||||
|
description = "S3 API server crate for the Garage object store"
|
||||||
|
repository = "https://git.deuxfleurs.fr/Deuxfleurs/garage"
|
||||||
|
readme = "../../README.md"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
path = "lib.rs"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
garage_model.workspace = true
|
||||||
|
garage_table.workspace = true
|
||||||
|
garage_block.workspace = true
|
||||||
|
garage_net.workspace = true
|
||||||
|
garage_util.workspace = true
|
||||||
|
garage_rpc.workspace = true
|
||||||
|
garage_api_common.workspace = true
|
||||||
|
|
||||||
|
aes-gcm.workspace = true
|
||||||
|
argon2.workspace = true
|
||||||
|
async-compression.workspace = true
|
||||||
|
async-trait.workspace = true
|
||||||
|
base64.workspace = true
|
||||||
|
bytes.workspace = true
|
||||||
|
chrono.workspace = true
|
||||||
|
crc32fast.workspace = true
|
||||||
|
crc32c.workspace = true
|
||||||
|
crypto-common.workspace = true
|
||||||
|
err-derive.workspace = true
|
||||||
|
hex.workspace = true
|
||||||
|
hmac.workspace = true
|
||||||
|
idna.workspace = true
|
||||||
|
tracing.workspace = true
|
||||||
|
md-5.workspace = true
|
||||||
|
nom.workspace = true
|
||||||
|
pin-project.workspace = true
|
||||||
|
sha1.workspace = true
|
||||||
|
sha2.workspace = true
|
||||||
|
|
||||||
|
futures.workspace = true
|
||||||
|
futures-util.workspace = true
|
||||||
|
tokio.workspace = true
|
||||||
|
tokio-stream.workspace = true
|
||||||
|
tokio-util.workspace = true
|
||||||
|
|
||||||
|
form_urlencoded.workspace = true
|
||||||
|
http.workspace = true
|
||||||
|
httpdate.workspace = true
|
||||||
|
http-range.workspace = true
|
||||||
|
http-body-util.workspace = true
|
||||||
|
hyper = { workspace = true, default-features = false, features = ["server", "http1"] }
|
||||||
|
hyper-util.workspace = true
|
||||||
|
multer.workspace = true
|
||||||
|
percent-encoding.workspace = true
|
||||||
|
roxmltree.workspace = true
|
||||||
|
url.workspace = true
|
||||||
|
|
||||||
|
serde.workspace = true
|
||||||
|
serde_bytes.workspace = true
|
||||||
|
serde_json.workspace = true
|
||||||
|
quick-xml.workspace = true
|
||||||
|
|
||||||
|
opentelemetry.workspace = true
|
||||||
|
opentelemetry-prometheus = { workspace = true, optional = true }
|
||||||
|
prometheus = { workspace = true, optional = true }
|
|
@ -20,15 +20,15 @@ use garage_rpc::system::ClusterHealthStatus;
|
||||||
use garage_util::error::Error as GarageError;
|
use garage_util::error::Error as GarageError;
|
||||||
use garage_util::socket_address::UnixOrTCPSocketAddress;
|
use garage_util::socket_address::UnixOrTCPSocketAddress;
|
||||||
|
|
||||||
use crate::generic_server::*;
|
use garage_api_common::generic_server::*;
|
||||||
|
|
||||||
use crate::admin::bucket::*;
|
use crate::bucket::*;
|
||||||
use crate::admin::cluster::*;
|
use crate::cluster::*;
|
||||||
use crate::admin::error::*;
|
use crate::error::*;
|
||||||
use crate::admin::key::*;
|
use crate::key::*;
|
||||||
use crate::admin::router_v0;
|
use crate::router_v0;
|
||||||
use crate::admin::router_v1::{Authorization, Endpoint};
|
use crate::router_v1::{Authorization, Endpoint};
|
||||||
use crate::helpers::*;
|
use garage_api_common::helpers::*;
|
||||||
|
|
||||||
pub type ResBody = BoxBody<Error>;
|
pub type ResBody = BoxBody<Error>;
|
||||||
|
|
||||||
|
|
|
@ -17,11 +17,11 @@ use garage_model::permission::*;
|
||||||
use garage_model::s3::mpu_table;
|
use garage_model::s3::mpu_table;
|
||||||
use garage_model::s3::object_table::*;
|
use garage_model::s3::object_table::*;
|
||||||
|
|
||||||
use crate::admin::api_server::ResBody;
|
use crate::api_server::ResBody;
|
||||||
use crate::admin::error::*;
|
use crate::error::*;
|
||||||
use crate::admin::key::ApiBucketKeyPerm;
|
use crate::key::ApiBucketKeyPerm;
|
||||||
use crate::common_error::CommonError;
|
use garage_api_common::common_error::CommonError;
|
||||||
use crate::helpers::*;
|
use garage_api_common::helpers::*;
|
||||||
|
|
||||||
pub async fn handle_list_buckets(garage: &Arc<Garage>) -> Result<Response<ResBody>, Error> {
|
pub async fn handle_list_buckets(garage: &Arc<Garage>) -> Result<Response<ResBody>, Error> {
|
||||||
let buckets = garage
|
let buckets = garage
|
||||||
|
|
|
@ -12,9 +12,9 @@ use garage_rpc::layout;
|
||||||
|
|
||||||
use garage_model::garage::Garage;
|
use garage_model::garage::Garage;
|
||||||
|
|
||||||
use crate::admin::api_server::ResBody;
|
use crate::api_server::ResBody;
|
||||||
use crate::admin::error::*;
|
use crate::error::*;
|
||||||
use crate::helpers::{json_ok_response, parse_json_body};
|
use garage_api_common::helpers::{json_ok_response, parse_json_body};
|
||||||
|
|
||||||
pub async fn handle_get_cluster_status(garage: &Arc<Garage>) -> Result<Response<ResBody>, Error> {
|
pub async fn handle_get_cluster_status(garage: &Arc<Garage>) -> Result<Response<ResBody>, Error> {
|
||||||
let layout = garage.system.cluster_layout();
|
let layout = garage.system.cluster_layout();
|
||||||
|
|
|
@ -6,10 +6,12 @@ use hyper::{HeaderMap, StatusCode};
|
||||||
|
|
||||||
pub use garage_model::helper::error::Error as HelperError;
|
pub use garage_model::helper::error::Error as HelperError;
|
||||||
|
|
||||||
use crate::common_error::CommonError;
|
use garage_api_common::common_error::CommonError;
|
||||||
pub use crate::common_error::{CommonErrorDerivative, OkOrBadRequest, OkOrInternalError};
|
pub use garage_api_common::common_error::{
|
||||||
use crate::generic_server::ApiError;
|
CommonErrorDerivative, OkOrBadRequest, OkOrInternalError,
|
||||||
use crate::helpers::*;
|
};
|
||||||
|
use garage_api_common::generic_server::ApiError;
|
||||||
|
use garage_api_common::helpers::*;
|
||||||
|
|
||||||
/// Errors of this crate
|
/// Errors of this crate
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
|
|
|
@ -9,9 +9,9 @@ use garage_table::*;
|
||||||
use garage_model::garage::Garage;
|
use garage_model::garage::Garage;
|
||||||
use garage_model::key_table::*;
|
use garage_model::key_table::*;
|
||||||
|
|
||||||
use crate::admin::api_server::ResBody;
|
use crate::api_server::ResBody;
|
||||||
use crate::admin::error::*;
|
use crate::error::*;
|
||||||
use crate::helpers::*;
|
use garage_api_common::helpers::*;
|
||||||
|
|
||||||
pub async fn handle_list_keys(garage: &Arc<Garage>) -> Result<Response<ResBody>, Error> {
|
pub async fn handle_list_keys(garage: &Arc<Garage>) -> Result<Response<ResBody>, Error> {
|
||||||
let res = garage
|
let res = garage
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#[macro_use]
|
||||||
|
extern crate tracing;
|
||||||
|
|
||||||
pub mod api_server;
|
pub mod api_server;
|
||||||
mod error;
|
mod error;
|
||||||
mod router_v0;
|
mod router_v0;
|
|
@ -2,8 +2,8 @@ use std::borrow::Cow;
|
||||||
|
|
||||||
use hyper::{Method, Request};
|
use hyper::{Method, Request};
|
||||||
|
|
||||||
use crate::admin::error::*;
|
use crate::error::*;
|
||||||
use crate::router_macros::*;
|
use garage_api_common::router_macros::*;
|
||||||
|
|
||||||
router_match! {@func
|
router_match! {@func
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,9 @@ use std::borrow::Cow;
|
||||||
|
|
||||||
use hyper::{Method, Request};
|
use hyper::{Method, Request};
|
||||||
|
|
||||||
use crate::admin::error::*;
|
use crate::error::*;
|
||||||
use crate::admin::router_v0;
|
use crate::router_v0;
|
||||||
use crate::router_macros::*;
|
use garage_api_common::router_macros::*;
|
||||||
|
|
||||||
pub enum Authorization {
|
pub enum Authorization {
|
||||||
None,
|
None,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[package]
|
[package]
|
||||||
name = "garage_api"
|
name = "garage_api_common"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
authors = ["Alex Auvolat <alex@adnab.me>"]
|
authors = ["Alex Auvolat <alex@adnab.me>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
@ -70,5 +70,4 @@ opentelemetry-prometheus = { workspace = true, optional = true }
|
||||||
prometheus = { workspace = true, optional = true }
|
prometheus = { workspace = true, optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
k2v = [ "garage_util/k2v", "garage_model/k2v" ]
|
|
||||||
metrics = [ "opentelemetry-prometheus", "prometheus" ]
|
metrics = [ "opentelemetry-prometheus", "prometheus" ]
|
|
@ -118,14 +118,14 @@ impl TryFrom<HelperError> for CommonError {
|
||||||
/// This is used for helper functions that might return InvalidBucketName
|
/// This is used for helper functions that might return InvalidBucketName
|
||||||
/// or NoSuchBucket for instance, and we want to pass that error
|
/// or NoSuchBucket for instance, and we want to pass that error
|
||||||
/// up to our caller.
|
/// up to our caller.
|
||||||
pub(crate) fn pass_helper_error(err: HelperError) -> CommonError {
|
pub fn pass_helper_error(err: HelperError) -> CommonError {
|
||||||
match CommonError::try_from(err) {
|
match CommonError::try_from(err) {
|
||||||
Ok(e) => e,
|
Ok(e) => e,
|
||||||
Err(e) => panic!("Helper error `{}` should hot have happenned here", e),
|
Err(e) => panic!("Helper error `{}` should hot have happenned here", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn helper_error_as_internal(err: HelperError) -> CommonError {
|
pub fn helper_error_as_internal(err: HelperError) -> CommonError {
|
||||||
match err {
|
match err {
|
||||||
HelperError::Internal(e) => CommonError::InternalError(e),
|
HelperError::Internal(e) => CommonError::InternalError(e),
|
||||||
e => CommonError::InternalError(GarageError::Message(e.to_string())),
|
e => CommonError::InternalError(GarageError::Message(e.to_string())),
|
|
@ -36,7 +36,7 @@ use garage_util::socket_address::UnixOrTCPSocketAddress;
|
||||||
|
|
||||||
use crate::helpers::{BoxBody, ErrorBody};
|
use crate::helpers::{BoxBody, ErrorBody};
|
||||||
|
|
||||||
pub(crate) trait ApiEndpoint: Send + Sync + 'static {
|
pub trait ApiEndpoint: Send + Sync + 'static {
|
||||||
fn name(&self) -> &'static str;
|
fn name(&self) -> &'static str;
|
||||||
fn add_span_attributes(&self, span: SpanRef<'_>);
|
fn add_span_attributes(&self, span: SpanRef<'_>);
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ pub trait ApiError: std::error::Error + Send + Sync + 'static {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub(crate) trait ApiHandler: Send + Sync + 'static {
|
pub trait ApiHandler: Send + Sync + 'static {
|
||||||
const API_NAME: &'static str;
|
const API_NAME: &'static str;
|
||||||
const API_NAME_DISPLAY: &'static str;
|
const API_NAME_DISPLAY: &'static str;
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ pub(crate) trait ApiHandler: Send + Sync + 'static {
|
||||||
) -> Result<Response<BoxBody<Self::Error>>, Self::Error>;
|
) -> Result<Response<BoxBody<Self::Error>>, Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct ApiServer<A: ApiHandler> {
|
pub struct ApiServer<A: ApiHandler> {
|
||||||
region: String,
|
region: String,
|
||||||
api_handler: A,
|
api_handler: A,
|
||||||
|
|
|
@ -363,9 +363,9 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub(crate) struct CustomApiErrorBody {
|
pub struct CustomApiErrorBody {
|
||||||
pub(crate) code: String,
|
pub code: String,
|
||||||
pub(crate) message: String,
|
pub message: String,
|
||||||
pub(crate) region: String,
|
pub region: String,
|
||||||
pub(crate) path: String,
|
pub path: String,
|
||||||
}
|
}
|
|
@ -4,14 +4,9 @@ extern crate tracing;
|
||||||
|
|
||||||
pub mod common_error;
|
pub mod common_error;
|
||||||
|
|
||||||
mod encoding;
|
pub mod encoding;
|
||||||
pub mod generic_server;
|
pub mod generic_server;
|
||||||
pub mod helpers;
|
pub mod helpers;
|
||||||
mod router_macros;
|
pub mod router_macros;
|
||||||
/// This mode is public only to help testing. Don't expect stability here
|
/// This mode is public only to help testing. Don't expect stability here
|
||||||
pub mod signature;
|
pub mod signature;
|
||||||
|
|
||||||
pub mod admin;
|
|
||||||
#[cfg(feature = "k2v")]
|
|
||||||
pub mod k2v;
|
|
||||||
pub mod s3;
|
|
|
@ -1,5 +1,6 @@
|
||||||
/// This macro is used to generate very repetitive match {} blocks in this module
|
/// This macro is used to generate very repetitive match {} blocks in this module
|
||||||
/// It is _not_ made to be used anywhere else
|
/// It is _not_ made to be used anywhere else
|
||||||
|
#[macro_export]
|
||||||
macro_rules! router_match {
|
macro_rules! router_match {
|
||||||
(@match $enum:expr , [ $($endpoint:ident,)* ]) => {{
|
(@match $enum:expr , [ $($endpoint:ident,)* ]) => {{
|
||||||
// usage: router_match {@match my_enum, [ VariantWithField1, VariantWithField2 ..] }
|
// usage: router_match {@match my_enum, [ VariantWithField1, VariantWithField2 ..] }
|
||||||
|
@ -133,6 +134,7 @@ macro_rules! router_match {
|
||||||
|
|
||||||
/// This macro is used to generate part of the code in this module. It must be called only one, and
|
/// This macro is used to generate part of the code in this module. It must be called only one, and
|
||||||
/// is useless outside of this module.
|
/// is useless outside of this module.
|
||||||
|
#[macro_export]
|
||||||
macro_rules! generateQueryParameters {
|
macro_rules! generateQueryParameters {
|
||||||
(
|
(
|
||||||
keywords: [ $($kw_param:expr => $kw_name: ident),* ],
|
keywords: [ $($kw_param:expr => $kw_name: ident),* ],
|
||||||
|
@ -220,5 +222,5 @@ macro_rules! generateQueryParameters {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) use generateQueryParameters;
|
pub use generateQueryParameters;
|
||||||
pub(crate) use router_match;
|
pub use router_match;
|
|
@ -518,7 +518,7 @@ impl Authorization {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn parse_form(params: &HeaderMap) -> Result<Self, Error> {
|
pub fn parse_form(params: &HeaderMap) -> Result<Self, Error> {
|
||||||
let algorithm = params
|
let algorithm = params
|
||||||
.get(X_AMZ_ALGORITHM)
|
.get(X_AMZ_ALGORITHM)
|
||||||
.ok_or_bad_request("Missing X-Amz-Algorithm header")?
|
.ok_or_bad_request("Missing X-Amz-Algorithm header")?
|
75
src/api/k2v/Cargo.toml
Normal file
75
src/api/k2v/Cargo.toml
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
[package]
|
||||||
|
name = "garage_api_k2v"
|
||||||
|
version = "1.0.1"
|
||||||
|
authors = ["Alex Auvolat <alex@adnab.me>"]
|
||||||
|
edition = "2018"
|
||||||
|
license = "AGPL-3.0"
|
||||||
|
description = "S3 API server crate for the Garage object store"
|
||||||
|
repository = "https://git.deuxfleurs.fr/Deuxfleurs/garage"
|
||||||
|
readme = "../../README.md"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
path = "lib.rs"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
garage_model.workspace = true
|
||||||
|
garage_table.workspace = true
|
||||||
|
garage_block.workspace = true
|
||||||
|
garage_net.workspace = true
|
||||||
|
garage_util.workspace = true
|
||||||
|
garage_rpc.workspace = true
|
||||||
|
garage_api_common.workspace = true
|
||||||
|
garage_api_s3.workspace = true
|
||||||
|
|
||||||
|
aes-gcm.workspace = true
|
||||||
|
argon2.workspace = true
|
||||||
|
async-compression.workspace = true
|
||||||
|
async-trait.workspace = true
|
||||||
|
base64.workspace = true
|
||||||
|
bytes.workspace = true
|
||||||
|
chrono.workspace = true
|
||||||
|
crc32fast.workspace = true
|
||||||
|
crc32c.workspace = true
|
||||||
|
crypto-common.workspace = true
|
||||||
|
err-derive.workspace = true
|
||||||
|
hex.workspace = true
|
||||||
|
hmac.workspace = true
|
||||||
|
idna.workspace = true
|
||||||
|
tracing.workspace = true
|
||||||
|
md-5.workspace = true
|
||||||
|
nom.workspace = true
|
||||||
|
pin-project.workspace = true
|
||||||
|
sha1.workspace = true
|
||||||
|
sha2.workspace = true
|
||||||
|
|
||||||
|
futures.workspace = true
|
||||||
|
futures-util.workspace = true
|
||||||
|
tokio.workspace = true
|
||||||
|
tokio-stream.workspace = true
|
||||||
|
tokio-util.workspace = true
|
||||||
|
|
||||||
|
form_urlencoded.workspace = true
|
||||||
|
http.workspace = true
|
||||||
|
httpdate.workspace = true
|
||||||
|
http-range.workspace = true
|
||||||
|
http-body-util.workspace = true
|
||||||
|
hyper = { workspace = true, default-features = false, features = ["server", "http1"] }
|
||||||
|
hyper-util.workspace = true
|
||||||
|
multer.workspace = true
|
||||||
|
percent-encoding.workspace = true
|
||||||
|
roxmltree.workspace = true
|
||||||
|
url.workspace = true
|
||||||
|
|
||||||
|
serde.workspace = true
|
||||||
|
serde_bytes.workspace = true
|
||||||
|
serde_json.workspace = true
|
||||||
|
quick-xml.workspace = true
|
||||||
|
|
||||||
|
opentelemetry.workspace = true
|
||||||
|
opentelemetry-prometheus = { workspace = true, optional = true }
|
||||||
|
prometheus = { workspace = true, optional = true }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = [ "garage_util/k2v", "garage_model/k2v" ]
|
|
@ -12,19 +12,19 @@ use garage_util::socket_address::UnixOrTCPSocketAddress;
|
||||||
|
|
||||||
use garage_model::garage::Garage;
|
use garage_model::garage::Garage;
|
||||||
|
|
||||||
use crate::generic_server::*;
|
use crate::error::*;
|
||||||
use crate::k2v::error::*;
|
use garage_api_common::generic_server::*;
|
||||||
|
|
||||||
use crate::signature::verify_request;
|
use garage_api_common::signature::verify_request;
|
||||||
|
|
||||||
use crate::helpers::*;
|
use crate::batch::*;
|
||||||
use crate::k2v::batch::*;
|
use crate::index::*;
|
||||||
use crate::k2v::index::*;
|
use crate::item::*;
|
||||||
use crate::k2v::item::*;
|
use crate::router::Endpoint;
|
||||||
use crate::k2v::router::Endpoint;
|
use garage_api_common::helpers::*;
|
||||||
use crate::s3::cors::*;
|
use garage_api_s3::cors::*;
|
||||||
|
|
||||||
pub use crate::signature::streaming::ReqBody;
|
pub use garage_api_common::signature::streaming::ReqBody;
|
||||||
pub type ResBody = BoxBody<Error>;
|
pub type ResBody = BoxBody<Error>;
|
||||||
|
|
||||||
pub struct K2VApiServer {
|
pub struct K2VApiServer {
|
||||||
|
|
|
@ -6,11 +6,11 @@ use garage_table::{EnumerationOrder, TableSchema};
|
||||||
|
|
||||||
use garage_model::k2v::item_table::*;
|
use garage_model::k2v::item_table::*;
|
||||||
|
|
||||||
use crate::helpers::*;
|
|
||||||
use crate::k2v::api_server::{ReqBody, ResBody};
|
use crate::k2v::api_server::{ReqBody, ResBody};
|
||||||
use crate::k2v::error::*;
|
use crate::k2v::error::*;
|
||||||
use crate::k2v::item::parse_causality_token;
|
use crate::k2v::item::parse_causality_token;
|
||||||
use crate::k2v::range::read_range;
|
use crate::k2v::range::read_range;
|
||||||
|
use garage_api_common::helpers::*;
|
||||||
|
|
||||||
pub async fn handle_insert_batch(
|
pub async fn handle_insert_batch(
|
||||||
ctx: ReqCtx,
|
ctx: ReqCtx,
|
||||||
|
|
|
@ -2,12 +2,14 @@ use err_derive::Error;
|
||||||
use hyper::header::HeaderValue;
|
use hyper::header::HeaderValue;
|
||||||
use hyper::{HeaderMap, StatusCode};
|
use hyper::{HeaderMap, StatusCode};
|
||||||
|
|
||||||
use crate::common_error::CommonError;
|
use garage_api_common::common_error::CommonError;
|
||||||
pub(crate) use crate::common_error::{helper_error_as_internal, pass_helper_error};
|
pub(crate) use garage_api_common::common_error::{helper_error_as_internal, pass_helper_error};
|
||||||
pub use crate::common_error::{CommonErrorDerivative, OkOrBadRequest, OkOrInternalError};
|
pub use garage_api_common::common_error::{
|
||||||
use crate::generic_server::ApiError;
|
CommonErrorDerivative, OkOrBadRequest, OkOrInternalError,
|
||||||
use crate::helpers::*;
|
};
|
||||||
use crate::signature::error::Error as SignatureError;
|
use garage_api_common::generic_server::ApiError;
|
||||||
|
use garage_api_common::helpers::*;
|
||||||
|
use garage_api_common::signature::error::Error as SignatureError;
|
||||||
|
|
||||||
/// Errors of this crate
|
/// Errors of this crate
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
|
|
|
@ -5,10 +5,10 @@ use garage_table::util::*;
|
||||||
|
|
||||||
use garage_model::k2v::item_table::{BYTES, CONFLICTS, ENTRIES, VALUES};
|
use garage_model::k2v::item_table::{BYTES, CONFLICTS, ENTRIES, VALUES};
|
||||||
|
|
||||||
use crate::helpers::*;
|
use crate::api_server::ResBody;
|
||||||
use crate::k2v::api_server::ResBody;
|
use crate::error::*;
|
||||||
use crate::k2v::error::*;
|
use crate::range::read_range;
|
||||||
use crate::k2v::range::read_range;
|
use garage_api_common::helpers::*;
|
||||||
|
|
||||||
pub async fn handle_read_index(
|
pub async fn handle_read_index(
|
||||||
ctx: ReqCtx,
|
ctx: ReqCtx,
|
||||||
|
|
|
@ -6,9 +6,9 @@ use hyper::{Request, Response, StatusCode};
|
||||||
use garage_model::k2v::causality::*;
|
use garage_model::k2v::causality::*;
|
||||||
use garage_model::k2v::item_table::*;
|
use garage_model::k2v::item_table::*;
|
||||||
|
|
||||||
use crate::helpers::*;
|
use crate::api_server::{ReqBody, ResBody};
|
||||||
use crate::k2v::api_server::{ReqBody, ResBody};
|
use crate::error::*;
|
||||||
use crate::k2v::error::*;
|
use garage_api_common::helpers::*;
|
||||||
|
|
||||||
pub const X_GARAGE_CAUSALITY_TOKEN: &str = "X-Garage-Causality-Token";
|
pub const X_GARAGE_CAUSALITY_TOKEN: &str = "X-Garage-Causality-Token";
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#[macro_use]
|
||||||
|
extern crate tracing;
|
||||||
|
|
||||||
pub mod api_server;
|
pub mod api_server;
|
||||||
mod error;
|
mod error;
|
||||||
mod router;
|
mod router;
|
|
@ -7,8 +7,8 @@ use std::sync::Arc;
|
||||||
use garage_table::replication::TableShardedReplication;
|
use garage_table::replication::TableShardedReplication;
|
||||||
use garage_table::*;
|
use garage_table::*;
|
||||||
|
|
||||||
use crate::helpers::key_after_prefix;
|
use crate::error::*;
|
||||||
use crate::k2v::error::*;
|
use garage_api_common::helpers::key_after_prefix;
|
||||||
|
|
||||||
/// Read range in a Garage table.
|
/// Read range in a Garage table.
|
||||||
/// Returns (entries, more?, nextStart)
|
/// Returns (entries, more?, nextStart)
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use crate::k2v::error::*;
|
use crate::error::*;
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use hyper::{Method, Request};
|
use hyper::{Method, Request};
|
||||||
|
|
||||||
use crate::helpers::Authorization;
|
use garage_api_common::helpers::Authorization;
|
||||||
use crate::router_macros::{generateQueryParameters, router_match};
|
use garage_api_common::router_macros::{generateQueryParameters, router_match};
|
||||||
|
|
||||||
router_match! {@func
|
router_match! {@func
|
||||||
|
|
||||||
|
|
71
src/api/s3/Cargo.toml
Normal file
71
src/api/s3/Cargo.toml
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
[package]
|
||||||
|
name = "garage_api_s3"
|
||||||
|
version = "1.0.1"
|
||||||
|
authors = ["Alex Auvolat <alex@adnab.me>"]
|
||||||
|
edition = "2018"
|
||||||
|
license = "AGPL-3.0"
|
||||||
|
description = "S3 API server crate for the Garage object store"
|
||||||
|
repository = "https://git.deuxfleurs.fr/Deuxfleurs/garage"
|
||||||
|
readme = "../../README.md"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
path = "lib.rs"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
garage_model.workspace = true
|
||||||
|
garage_table.workspace = true
|
||||||
|
garage_block.workspace = true
|
||||||
|
garage_net.workspace = true
|
||||||
|
garage_util.workspace = true
|
||||||
|
garage_rpc.workspace = true
|
||||||
|
garage_api_common.workspace = true
|
||||||
|
|
||||||
|
aes-gcm.workspace = true
|
||||||
|
argon2.workspace = true
|
||||||
|
async-compression.workspace = true
|
||||||
|
async-trait.workspace = true
|
||||||
|
base64.workspace = true
|
||||||
|
bytes.workspace = true
|
||||||
|
chrono.workspace = true
|
||||||
|
crc32fast.workspace = true
|
||||||
|
crc32c.workspace = true
|
||||||
|
crypto-common.workspace = true
|
||||||
|
err-derive.workspace = true
|
||||||
|
hex.workspace = true
|
||||||
|
hmac.workspace = true
|
||||||
|
idna.workspace = true
|
||||||
|
tracing.workspace = true
|
||||||
|
md-5.workspace = true
|
||||||
|
nom.workspace = true
|
||||||
|
pin-project.workspace = true
|
||||||
|
sha1.workspace = true
|
||||||
|
sha2.workspace = true
|
||||||
|
|
||||||
|
futures.workspace = true
|
||||||
|
futures-util.workspace = true
|
||||||
|
tokio.workspace = true
|
||||||
|
tokio-stream.workspace = true
|
||||||
|
tokio-util.workspace = true
|
||||||
|
|
||||||
|
form_urlencoded.workspace = true
|
||||||
|
http.workspace = true
|
||||||
|
httpdate.workspace = true
|
||||||
|
http-range.workspace = true
|
||||||
|
http-body-util.workspace = true
|
||||||
|
hyper = { workspace = true, default-features = false, features = ["server", "http1"] }
|
||||||
|
hyper-util.workspace = true
|
||||||
|
multer.workspace = true
|
||||||
|
percent-encoding.workspace = true
|
||||||
|
roxmltree.workspace = true
|
||||||
|
url.workspace = true
|
||||||
|
|
||||||
|
serde.workspace = true
|
||||||
|
serde_bytes.workspace = true
|
||||||
|
serde_json.workspace = true
|
||||||
|
quick-xml.workspace = true
|
||||||
|
|
||||||
|
opentelemetry.workspace = true
|
||||||
|
opentelemetry-prometheus = { workspace = true, optional = true }
|
||||||
|
prometheus = { workspace = true, optional = true }
|
|
@ -14,26 +14,26 @@ use garage_util::socket_address::UnixOrTCPSocketAddress;
|
||||||
use garage_model::garage::Garage;
|
use garage_model::garage::Garage;
|
||||||
use garage_model::key_table::Key;
|
use garage_model::key_table::Key;
|
||||||
|
|
||||||
use crate::generic_server::*;
|
use crate::error::*;
|
||||||
use crate::s3::error::*;
|
use garage_api_common::generic_server::*;
|
||||||
|
|
||||||
use crate::signature::verify_request;
|
use garage_api_common::signature::verify_request;
|
||||||
|
|
||||||
use crate::helpers::*;
|
use crate::bucket::*;
|
||||||
use crate::s3::bucket::*;
|
use crate::copy::*;
|
||||||
use crate::s3::copy::*;
|
use crate::cors::*;
|
||||||
use crate::s3::cors::*;
|
use crate::delete::*;
|
||||||
use crate::s3::delete::*;
|
use crate::get::*;
|
||||||
use crate::s3::get::*;
|
use crate::lifecycle::*;
|
||||||
use crate::s3::lifecycle::*;
|
use crate::list::*;
|
||||||
use crate::s3::list::*;
|
use crate::multipart::*;
|
||||||
use crate::s3::multipart::*;
|
use crate::post_object::handle_post_object;
|
||||||
use crate::s3::post_object::handle_post_object;
|
use crate::put::*;
|
||||||
use crate::s3::put::*;
|
use crate::router::Endpoint;
|
||||||
use crate::s3::router::Endpoint;
|
use crate::website::*;
|
||||||
use crate::s3::website::*;
|
use garage_api_common::helpers::*;
|
||||||
|
|
||||||
pub use crate::signature::streaming::ReqBody;
|
pub use garage_api_common::signature::streaming::ReqBody;
|
||||||
pub type ResBody = BoxBody<Error>;
|
pub type ResBody = BoxBody<Error>;
|
||||||
|
|
||||||
pub struct S3ApiServer {
|
pub struct S3ApiServer {
|
||||||
|
|
|
@ -13,12 +13,12 @@ use garage_util::crdt::*;
|
||||||
use garage_util::data::*;
|
use garage_util::data::*;
|
||||||
use garage_util::time::*;
|
use garage_util::time::*;
|
||||||
|
|
||||||
use crate::common_error::CommonError;
|
use crate::api_server::{ReqBody, ResBody};
|
||||||
use crate::helpers::*;
|
use crate::error::*;
|
||||||
use crate::s3::api_server::{ReqBody, ResBody};
|
use crate::xml as s3_xml;
|
||||||
use crate::s3::error::*;
|
use garage_api_common::common_error::CommonError;
|
||||||
use crate::s3::xml as s3_xml;
|
use garage_api_common::helpers::*;
|
||||||
use crate::signature::verify_signed_content;
|
use garage_api_common::signature::verify_signed_content;
|
||||||
|
|
||||||
pub fn handle_get_bucket_location(ctx: ReqCtx) -> Result<Response<ResBody>, Error> {
|
pub fn handle_get_bucket_location(ctx: ReqCtx) -> Result<Response<ResBody>, Error> {
|
||||||
let ReqCtx { garage, .. } = ctx;
|
let ReqCtx { garage, .. } = ctx;
|
||||||
|
|
|
@ -15,7 +15,7 @@ use garage_util::error::OkOrMessage;
|
||||||
|
|
||||||
use garage_model::s3::object_table::*;
|
use garage_model::s3::object_table::*;
|
||||||
|
|
||||||
use crate::s3::error::*;
|
use crate::error::*;
|
||||||
|
|
||||||
pub const X_AMZ_CHECKSUM_ALGORITHM: HeaderName =
|
pub const X_AMZ_CHECKSUM_ALGORITHM: HeaderName =
|
||||||
HeaderName::from_static("x-amz-checksum-algorithm");
|
HeaderName::from_static("x-amz-checksum-algorithm");
|
||||||
|
|
|
@ -20,15 +20,15 @@ use garage_model::s3::mpu_table::*;
|
||||||
use garage_model::s3::object_table::*;
|
use garage_model::s3::object_table::*;
|
||||||
use garage_model::s3::version_table::*;
|
use garage_model::s3::version_table::*;
|
||||||
|
|
||||||
use crate::helpers::*;
|
use crate::api_server::{ReqBody, ResBody};
|
||||||
use crate::s3::api_server::{ReqBody, ResBody};
|
use crate::checksum::*;
|
||||||
use crate::s3::checksum::*;
|
use crate::encryption::EncryptionParams;
|
||||||
use crate::s3::encryption::EncryptionParams;
|
use crate::error::*;
|
||||||
use crate::s3::error::*;
|
use crate::get::full_object_byte_stream;
|
||||||
use crate::s3::get::full_object_byte_stream;
|
use crate::multipart;
|
||||||
use crate::s3::multipart;
|
use crate::put::{get_headers, save_stream, ChecksumMode, SaveStreamResult};
|
||||||
use crate::s3::put::{get_headers, save_stream, ChecksumMode, SaveStreamResult};
|
use crate::xml::{self as s3_xml, xmlns_tag};
|
||||||
use crate::s3::xml::{self as s3_xml, xmlns_tag};
|
use garage_api_common::helpers::*;
|
||||||
|
|
||||||
// -------- CopyObject ---------
|
// -------- CopyObject ---------
|
||||||
|
|
||||||
|
|
|
@ -15,12 +15,12 @@ use http_body_util::BodyExt;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::common_error::{helper_error_as_internal, CommonError};
|
use crate::api_server::{ReqBody, ResBody};
|
||||||
use crate::helpers::*;
|
use crate::error::*;
|
||||||
use crate::s3::api_server::{ReqBody, ResBody};
|
use crate::xml::{to_xml_with_header, xmlns_tag, IntValue, Value};
|
||||||
use crate::s3::error::*;
|
use garage_api_common::common_error::{helper_error_as_internal, CommonError};
|
||||||
use crate::s3::xml::{to_xml_with_header, xmlns_tag, IntValue, Value};
|
use garage_api_common::helpers::*;
|
||||||
use crate::signature::verify_signed_content;
|
use garage_api_common::signature::verify_signed_content;
|
||||||
|
|
||||||
use garage_model::bucket_table::{Bucket, BucketParams, CorsRule as GarageCorsRule};
|
use garage_model::bucket_table::{Bucket, BucketParams, CorsRule as GarageCorsRule};
|
||||||
use garage_model::garage::Garage;
|
use garage_model::garage::Garage;
|
||||||
|
|
|
@ -5,12 +5,12 @@ use garage_util::data::*;
|
||||||
|
|
||||||
use garage_model::s3::object_table::*;
|
use garage_model::s3::object_table::*;
|
||||||
|
|
||||||
use crate::helpers::*;
|
use crate::api_server::{ReqBody, ResBody};
|
||||||
use crate::s3::api_server::{ReqBody, ResBody};
|
use crate::error::*;
|
||||||
use crate::s3::error::*;
|
use crate::put::next_timestamp;
|
||||||
use crate::s3::put::next_timestamp;
|
use crate::xml as s3_xml;
|
||||||
use crate::s3::xml as s3_xml;
|
use garage_api_common::helpers::*;
|
||||||
use crate::signature::verify_signed_content;
|
use garage_api_common::signature::verify_signed_content;
|
||||||
|
|
||||||
async fn handle_delete_internal(ctx: &ReqCtx, key: &str) -> Result<(Uuid, Uuid), Error> {
|
async fn handle_delete_internal(ctx: &ReqCtx, key: &str) -> Result<(Uuid, Uuid), Error> {
|
||||||
let ReqCtx {
|
let ReqCtx {
|
||||||
|
|
|
@ -28,9 +28,9 @@ use garage_util::migrate::Migrate;
|
||||||
use garage_model::garage::Garage;
|
use garage_model::garage::Garage;
|
||||||
use garage_model::s3::object_table::{ObjectVersionEncryption, ObjectVersionMetaInner};
|
use garage_model::s3::object_table::{ObjectVersionEncryption, ObjectVersionMetaInner};
|
||||||
|
|
||||||
use crate::common_error::*;
|
use crate::checksum::Md5Checksum;
|
||||||
use crate::s3::checksum::Md5Checksum;
|
use crate::error::Error;
|
||||||
use crate::s3::error::Error;
|
use garage_api_common::common_error::*;
|
||||||
|
|
||||||
const X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_ALGORITHM: HeaderName =
|
const X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_ALGORITHM: HeaderName =
|
||||||
HeaderName::from_static("x-amz-server-side-encryption-customer-algorithm");
|
HeaderName::from_static("x-amz-server-side-encryption-customer-algorithm");
|
||||||
|
|
|
@ -6,13 +6,18 @@ use hyper::{HeaderMap, StatusCode};
|
||||||
|
|
||||||
use garage_model::helper::error::Error as HelperError;
|
use garage_model::helper::error::Error as HelperError;
|
||||||
|
|
||||||
pub(crate) use crate::common_error::pass_helper_error;
|
pub(crate) use garage_api_common::common_error::pass_helper_error;
|
||||||
use crate::common_error::{helper_error_as_internal, CommonError};
|
|
||||||
pub use crate::common_error::{CommonErrorDerivative, OkOrBadRequest, OkOrInternalError};
|
use garage_api_common::common_error::{helper_error_as_internal, CommonError};
|
||||||
use crate::generic_server::ApiError;
|
|
||||||
use crate::helpers::*;
|
pub use garage_api_common::common_error::{
|
||||||
use crate::s3::xml as s3_xml;
|
CommonErrorDerivative, OkOrBadRequest, OkOrInternalError,
|
||||||
use crate::signature::error::Error as SignatureError;
|
};
|
||||||
|
|
||||||
|
use crate::xml as s3_xml;
|
||||||
|
use garage_api_common::generic_server::ApiError;
|
||||||
|
use garage_api_common::helpers::*;
|
||||||
|
use garage_api_common::signature::error::Error as SignatureError;
|
||||||
|
|
||||||
/// Errors of this crate
|
/// Errors of this crate
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
|
|
|
@ -25,11 +25,11 @@ use garage_model::garage::Garage;
|
||||||
use garage_model::s3::object_table::*;
|
use garage_model::s3::object_table::*;
|
||||||
use garage_model::s3::version_table::*;
|
use garage_model::s3::version_table::*;
|
||||||
|
|
||||||
use crate::helpers::*;
|
use crate::api_server::ResBody;
|
||||||
use crate::s3::api_server::ResBody;
|
use crate::checksum::{add_checksum_response_headers, X_AMZ_CHECKSUM_MODE};
|
||||||
use crate::s3::checksum::{add_checksum_response_headers, X_AMZ_CHECKSUM_MODE};
|
use crate::encryption::EncryptionParams;
|
||||||
use crate::s3::encryption::EncryptionParams;
|
use crate::error::*;
|
||||||
use crate::s3::error::*;
|
use garage_api_common::helpers::*;
|
||||||
|
|
||||||
const X_AMZ_MP_PARTS_COUNT: &str = "x-amz-mp-parts-count";
|
const X_AMZ_MP_PARTS_COUNT: &str = "x-amz-mp-parts-count";
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#[macro_use]
|
||||||
|
extern crate tracing;
|
||||||
|
|
||||||
pub mod api_server;
|
pub mod api_server;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
|
|
@ -5,11 +5,11 @@ use hyper::{Request, Response, StatusCode};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::helpers::*;
|
use crate::api_server::{ReqBody, ResBody};
|
||||||
use crate::s3::api_server::{ReqBody, ResBody};
|
use crate::error::*;
|
||||||
use crate::s3::error::*;
|
use crate::xml::{to_xml_with_header, xmlns_tag, IntValue, Value};
|
||||||
use crate::s3::xml::{to_xml_with_header, xmlns_tag, IntValue, Value};
|
use garage_api_common::helpers::*;
|
||||||
use crate::signature::verify_signed_content;
|
use garage_api_common::signature::verify_signed_content;
|
||||||
|
|
||||||
use garage_model::bucket_table::{
|
use garage_model::bucket_table::{
|
||||||
parse_lifecycle_date, Bucket, LifecycleExpiration as GarageLifecycleExpiration,
|
parse_lifecycle_date, Bucket, LifecycleExpiration as GarageLifecycleExpiration,
|
||||||
|
|
|
@ -13,13 +13,13 @@ use garage_model::s3::object_table::*;
|
||||||
|
|
||||||
use garage_table::EnumerationOrder;
|
use garage_table::EnumerationOrder;
|
||||||
|
|
||||||
use crate::encoding::*;
|
use crate::api_server::{ReqBody, ResBody};
|
||||||
use crate::helpers::*;
|
use crate::encryption::EncryptionParams;
|
||||||
use crate::s3::api_server::{ReqBody, ResBody};
|
use crate::error::*;
|
||||||
use crate::s3::encryption::EncryptionParams;
|
use crate::multipart as s3_multipart;
|
||||||
use crate::s3::error::*;
|
use crate::xml as s3_xml;
|
||||||
use crate::s3::multipart as s3_multipart;
|
use garage_api_common::encoding::*;
|
||||||
use crate::s3::xml as s3_xml;
|
use garage_api_common::helpers::*;
|
||||||
|
|
||||||
const DUMMY_NAME: &str = "Dummy Key";
|
const DUMMY_NAME: &str = "Dummy Key";
|
||||||
const DUMMY_KEY: &str = "GKDummyKey";
|
const DUMMY_KEY: &str = "GKDummyKey";
|
||||||
|
|
|
@ -15,14 +15,14 @@ use garage_model::s3::mpu_table::*;
|
||||||
use garage_model::s3::object_table::*;
|
use garage_model::s3::object_table::*;
|
||||||
use garage_model::s3::version_table::*;
|
use garage_model::s3::version_table::*;
|
||||||
|
|
||||||
use crate::helpers::*;
|
use crate::api_server::{ReqBody, ResBody};
|
||||||
use crate::s3::api_server::{ReqBody, ResBody};
|
use crate::checksum::*;
|
||||||
use crate::s3::checksum::*;
|
use crate::encryption::EncryptionParams;
|
||||||
use crate::s3::encryption::EncryptionParams;
|
use crate::error::*;
|
||||||
use crate::s3::error::*;
|
use crate::put::*;
|
||||||
use crate::s3::put::*;
|
use crate::xml as s3_xml;
|
||||||
use crate::s3::xml as s3_xml;
|
use garage_api_common::helpers::*;
|
||||||
use crate::signature::verify_signed_content;
|
use garage_api_common::signature::verify_signed_content;
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
|
|
||||||
|
|
|
@ -16,15 +16,15 @@ use serde::Deserialize;
|
||||||
use garage_model::garage::Garage;
|
use garage_model::garage::Garage;
|
||||||
use garage_model::s3::object_table::*;
|
use garage_model::s3::object_table::*;
|
||||||
|
|
||||||
use crate::helpers::*;
|
use crate::api_server::ResBody;
|
||||||
use crate::s3::api_server::ResBody;
|
use crate::checksum::*;
|
||||||
use crate::s3::checksum::*;
|
use crate::cors::*;
|
||||||
use crate::s3::cors::*;
|
use crate::encryption::EncryptionParams;
|
||||||
use crate::s3::encryption::EncryptionParams;
|
use crate::error::*;
|
||||||
use crate::s3::error::*;
|
use crate::put::{get_headers, save_stream, ChecksumMode};
|
||||||
use crate::s3::put::{get_headers, save_stream, ChecksumMode};
|
use crate::xml as s3_xml;
|
||||||
use crate::s3::xml as s3_xml;
|
use garage_api_common::helpers::*;
|
||||||
use crate::signature::payload::{verify_v4, Authorization};
|
use garage_api_common::signature::payload::{verify_v4, Authorization};
|
||||||
|
|
||||||
pub async fn handle_post_object(
|
pub async fn handle_post_object(
|
||||||
garage: Arc<Garage>,
|
garage: Arc<Garage>,
|
||||||
|
|
|
@ -30,11 +30,11 @@ use garage_model::s3::block_ref_table::*;
|
||||||
use garage_model::s3::object_table::*;
|
use garage_model::s3::object_table::*;
|
||||||
use garage_model::s3::version_table::*;
|
use garage_model::s3::version_table::*;
|
||||||
|
|
||||||
use crate::helpers::*;
|
use crate::api_server::{ReqBody, ResBody};
|
||||||
use crate::s3::api_server::{ReqBody, ResBody};
|
use crate::checksum::*;
|
||||||
use crate::s3::checksum::*;
|
use crate::encryption::EncryptionParams;
|
||||||
use crate::s3::encryption::EncryptionParams;
|
use crate::error::*;
|
||||||
use crate::s3::error::*;
|
use garage_api_common::helpers::*;
|
||||||
|
|
||||||
const PUT_BLOCKS_MAX_PARALLEL: usize = 3;
|
const PUT_BLOCKS_MAX_PARALLEL: usize = 3;
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,9 @@ use std::borrow::Cow;
|
||||||
use hyper::header::HeaderValue;
|
use hyper::header::HeaderValue;
|
||||||
use hyper::{HeaderMap, Method, Request};
|
use hyper::{HeaderMap, Method, Request};
|
||||||
|
|
||||||
use crate::helpers::Authorization;
|
use crate::error::*;
|
||||||
use crate::router_macros::{generateQueryParameters, router_match};
|
use garage_api_common::helpers::Authorization;
|
||||||
use crate::s3::error::*;
|
use garage_api_common::router_macros::{generateQueryParameters, router_match};
|
||||||
|
|
||||||
router_match! {@func
|
router_match! {@func
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,11 @@ use http_body_util::BodyExt;
|
||||||
use hyper::{Request, Response, StatusCode};
|
use hyper::{Request, Response, StatusCode};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::helpers::*;
|
use crate::api_server::{ReqBody, ResBody};
|
||||||
use crate::s3::api_server::{ReqBody, ResBody};
|
use crate::error::*;
|
||||||
use crate::s3::error::*;
|
use crate::xml::{to_xml_with_header, xmlns_tag, IntValue, Value};
|
||||||
use crate::s3::xml::{to_xml_with_header, xmlns_tag, IntValue, Value};
|
use garage_api_common::helpers::*;
|
||||||
use crate::signature::verify_signed_content;
|
use garage_api_common::signature::verify_signed_content;
|
||||||
|
|
||||||
use garage_model::bucket_table::*;
|
use garage_model::bucket_table::*;
|
||||||
use garage_util::data::*;
|
use garage_util::data::*;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use quick_xml::se::to_string;
|
use quick_xml::se::to_string;
|
||||||
use serde::{Deserialize, Serialize, Serializer};
|
use serde::{Deserialize, Serialize, Serializer};
|
||||||
|
|
||||||
use crate::s3::error::Error as ApiError;
|
use crate::error::Error as ApiError;
|
||||||
|
|
||||||
pub fn to_xml_with_header<T: Serialize>(x: &T) -> Result<String, ApiError> {
|
pub fn to_xml_with_header<T: Serialize>(x: &T) -> Result<String, ApiError> {
|
||||||
let mut xml = r#"<?xml version="1.0" encoding="UTF-8"?>"#.to_string();
|
let mut xml = r#"<?xml version="1.0" encoding="UTF-8"?>"#.to_string();
|
||||||
|
|
|
@ -23,7 +23,10 @@ path = "tests/lib.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
format_table.workspace = true
|
format_table.workspace = true
|
||||||
garage_db.workspace = true
|
garage_db.workspace = true
|
||||||
garage_api.workspace = true
|
garage_api_common.workspace = true
|
||||||
|
garage_api_admin.workspace = true
|
||||||
|
garage_api_s3.workspace = true
|
||||||
|
garage_api_k2v = { workspace = true, optional = true }
|
||||||
garage_block.workspace = true
|
garage_block.workspace = true
|
||||||
garage_model.workspace = true
|
garage_model.workspace = true
|
||||||
garage_net.workspace = true
|
garage_net.workspace = true
|
||||||
|
@ -84,7 +87,7 @@ k2v-client.workspace = true
|
||||||
[features]
|
[features]
|
||||||
default = [ "bundled-libs", "metrics", "lmdb", "sqlite", "k2v" ]
|
default = [ "bundled-libs", "metrics", "lmdb", "sqlite", "k2v" ]
|
||||||
|
|
||||||
k2v = [ "garage_util/k2v", "garage_api/k2v" ]
|
k2v = [ "garage_util/k2v", "garage_api_k2v" ]
|
||||||
|
|
||||||
# Database engines
|
# Database engines
|
||||||
lmdb = [ "garage_model/lmdb" ]
|
lmdb = [ "garage_model/lmdb" ]
|
||||||
|
@ -95,7 +98,7 @@ consul-discovery = [ "garage_rpc/consul-discovery" ]
|
||||||
# Automatic registration and discovery via Kubernetes API
|
# Automatic registration and discovery via Kubernetes API
|
||||||
kubernetes-discovery = [ "garage_rpc/kubernetes-discovery" ]
|
kubernetes-discovery = [ "garage_rpc/kubernetes-discovery" ]
|
||||||
# Prometheus exporter (/metrics endpoint).
|
# Prometheus exporter (/metrics endpoint).
|
||||||
metrics = [ "garage_api/metrics", "opentelemetry-prometheus", "prometheus" ]
|
metrics = [ "garage_api_common/metrics", "opentelemetry-prometheus", "prometheus" ]
|
||||||
# Exporter for the OpenTelemetry Collector.
|
# Exporter for the OpenTelemetry Collector.
|
||||||
telemetry-otlp = [ "opentelemetry-otlp" ]
|
telemetry-otlp = [ "opentelemetry-otlp" ]
|
||||||
# Logging to syslog
|
# Logging to syslog
|
||||||
|
|
|
@ -14,7 +14,8 @@ path = "lib.rs"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
garage_api.workspace = true
|
garage_api_common.workspace = true
|
||||||
|
garage_api_s3.workspace = true
|
||||||
garage_model.workspace = true
|
garage_model.workspace = true
|
||||||
garage_util.workspace = true
|
garage_util.workspace = true
|
||||||
garage_table.workspace = true
|
garage_table.workspace = true
|
||||||
|
|
Loading…
Add table
Reference in a new issue