mirror of
https://github.com/deuxfleurs-org/garage.git
synced 2026-08-12 07:16:52 +00:00
Implement multipart uploads
This commit is contained in:
+53
-30
@@ -3,7 +3,6 @@ use std::net::SocketAddr;
|
||||
use std::sync::Arc;
|
||||
|
||||
use futures::future::Future;
|
||||
use hyper::body::{Bytes, HttpBody};
|
||||
use hyper::server::conn::AddrStream;
|
||||
use hyper::service::{make_service_fn, service_fn};
|
||||
use hyper::{Body, Method, Request, Response, Server};
|
||||
@@ -15,11 +14,9 @@ use garage_core::garage::Garage;
|
||||
use crate::http_util::*;
|
||||
use crate::signature::check_signature;
|
||||
|
||||
use crate::s3_get::{handle_get, handle_head};
|
||||
use crate::s3_list::handle_list;
|
||||
use crate::s3_put::{handle_delete, handle_put};
|
||||
|
||||
pub type BodyType = Box<dyn HttpBody<Data = Bytes, Error = Error> + Send + Unpin>;
|
||||
use crate::s3_get::*;
|
||||
use crate::s3_list::*;
|
||||
use crate::s3_put::*;
|
||||
|
||||
pub async fn run_api_server(
|
||||
garage: Arc<Garage>,
|
||||
@@ -100,33 +97,62 @@ async fn handler_inner(
|
||||
)));
|
||||
}
|
||||
|
||||
let mut params = HashMap::new();
|
||||
if let Some(query) = req.uri().query() {
|
||||
let query_pairs = url::form_urlencoded::parse(query.as_bytes());
|
||||
for (key, val) in query_pairs {
|
||||
params.insert(key.to_lowercase(), val.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(key) = key {
|
||||
match req.method() {
|
||||
&Method::HEAD => Ok(handle_head(garage, &bucket, &key).await?),
|
||||
&Method::GET => Ok(handle_get(garage, &bucket, &key).await?),
|
||||
&Method::HEAD => {
|
||||
// HeadObject query
|
||||
Ok(handle_head(garage, &bucket, &key).await?)
|
||||
}
|
||||
&Method::GET => {
|
||||
// GetObject query
|
||||
Ok(handle_get(garage, &bucket, &key).await?)
|
||||
}
|
||||
&Method::PUT => {
|
||||
let mime_type = req
|
||||
.headers()
|
||||
.get(hyper::header::CONTENT_TYPE)
|
||||
.map(|x| x.to_str())
|
||||
.unwrap_or(Ok("blob"))?
|
||||
.to_string();
|
||||
let version_uuid =
|
||||
handle_put(garage, &mime_type, &bucket, &key, req.into_body()).await?;
|
||||
let response = format!("{}\n", hex::encode(version_uuid,));
|
||||
Ok(Response::new(Box::new(BytesBody::from(response))))
|
||||
if ["partnumber", "uploadid"]
|
||||
.iter()
|
||||
.all(|x| params.contains_key(&x.to_string()))
|
||||
{
|
||||
let part_number = params.get("partnumber").unwrap();
|
||||
let upload_id = params.get("uploadid").unwrap();
|
||||
Ok(handle_put_part(garage, req, &bucket, &key, part_number, upload_id).await?)
|
||||
} else {
|
||||
// PutObject query
|
||||
Ok(handle_put(garage, req, &bucket, &key).await?)
|
||||
}
|
||||
}
|
||||
&Method::DELETE => {
|
||||
// DeleteObject query
|
||||
let version_uuid = handle_delete(garage, &bucket, &key).await?;
|
||||
let response = format!("{}\n", hex::encode(version_uuid,));
|
||||
let response = format!("{}\n", hex::encode(version_uuid));
|
||||
Ok(Response::new(Box::new(BytesBody::from(response))))
|
||||
}
|
||||
&Method::POST => {
|
||||
if params.contains_key(&"uploads".to_string()) {
|
||||
// CreateMultipartUpload call
|
||||
Ok(handle_create_multipart_upload(garage, &req, &bucket, &key).await?)
|
||||
} else if params.contains_key(&"uploadid".to_string()) {
|
||||
let upload_id = params.get("uploadid").unwrap();
|
||||
Ok(handle_complete_multipart_upload(garage, req, &bucket, &key, upload_id).await?)
|
||||
} else {
|
||||
Err(Error::BadRequest(format!(
|
||||
"Not a CreateMultipartUpload call, what is it?"
|
||||
)))
|
||||
}
|
||||
}
|
||||
_ => Err(Error::BadRequest(format!("Invalid method"))),
|
||||
}
|
||||
} else {
|
||||
match req.method() {
|
||||
&Method::PUT | &Method::HEAD => {
|
||||
// If PUT: corresponds to a bucket creation call
|
||||
// If PUT: CreateBucket, if HEAD: HeadBucket
|
||||
// If we're here, the bucket already exists, so just answer ok
|
||||
let empty_body: BodyType = Box::new(BytesBody::from(vec![]));
|
||||
let response = Response::builder()
|
||||
@@ -135,21 +161,18 @@ async fn handler_inner(
|
||||
.unwrap();
|
||||
Ok(response)
|
||||
}
|
||||
&Method::DELETE => Err(Error::Forbidden(
|
||||
"Cannot delete buckets using S3 api, please talk to Garage directly".into(),
|
||||
)),
|
||||
&Method::DELETE => {
|
||||
// DeleteBucket query
|
||||
Err(Error::Forbidden(
|
||||
"Cannot delete buckets using S3 api, please talk to Garage directly".into(),
|
||||
))
|
||||
}
|
||||
&Method::GET => {
|
||||
let mut params = HashMap::new();
|
||||
if let Some(query) = req.uri().query() {
|
||||
let query_pairs = url::form_urlencoded::parse(query.as_bytes());
|
||||
for (key, val) in query_pairs {
|
||||
params.insert(key.to_lowercase(), val.to_string());
|
||||
}
|
||||
}
|
||||
if ["delimiter", "prefix"]
|
||||
.iter()
|
||||
.all(|x| params.contains_key(&x.to_string()))
|
||||
{
|
||||
// ListObjects query
|
||||
let delimiter = params.get("delimiter").unwrap();
|
||||
let max_keys = params
|
||||
.get("max-keys")
|
||||
|
||||
Reference in New Issue
Block a user