use super::*; use crate::api::*; use async_trait::async_trait; use hyper::{http::request::Parts, Body, Method}; use hyper::{Response, StatusCode}; use std::collections::HashMap; use std::fmt::Debug; pub enum Ops { ListBuckets(ListBucketsParams), GetBucket(GetBucketParams), PutBucket(PutBucketParams), DeleteBucket(DeleteBucketParams), ListObjects(ListObjectsParams), GetObject(GetObjectParams), PutObject(PutObjectParams), DeleteObject(DeleteObjectParams), } #[async_trait] pub trait Op { fn parse(req: HttpRequest) -> Self; async fn execute(&self, api: &dyn ApiLayer) -> HttpResult; } // pub fn parse_request(req: HttpRequest) -> Result { // // path style addressing // assert!(req.uri().path().starts_with("/")); // let path_items: Vec<_> = req.uri().path()[1..].splitn(2, "/").collect(); // let bucket = path_items.get(0).unwrap_or(&""); // let key = path_items.get(1).unwrap_or(&""); // if bucket.is_empty() { // Ok(Ops::ListBuckets(ListBucketsParams {})) // } else if key.is_empty() { // match req.method() { // Method::GET => Ok(Ops::ListObjects(ListObjectsParams { // bucket: bucket.to_string(), // })), // Method::HEAD => Ok(Ops::GetBucket(GetBucketParams { // bucket: bucket.to_string(), // })), // Method::PUT => Ok(Ops::PutBucket(PutBucketParams { // bucket: bucket.to_string(), // })), // Method::DELETE => Ok(Ops::DeleteBucket(DeleteBucketParams { // bucket: bucket.to_string(), // })), // } // } else { // match req.method() { // Method::GET => Ok(Ops::GetObject(GetObjectParams { // bucket: bucket.to_string(), // key: key.to_string(), // })), // Method::HEAD => Ok(Ops::GetObject(GetObjectParams { // bucket: bucket.to_string(), // key: key.to_string(), // })), // Method::PUT => Ok(Ops::PutObject(PutObjectParams { // bucket: bucket.to_string(), // key: key.to_string(), // })), // Method::DELETE => Ok(Ops::DeleteObject(DeleteObjectParams { // bucket: bucket.to_string(), // key: key.to_string(), // })), // } // } // } // #[async_trait] // pub trait ServerOp: Debug + Send + Sync + Clone { // type Params; // type Reply; // async fn call(self, req: HttpRequest, api: &dyn ApiLayer) -> HttpResult; // } // #[async_trait] // impl ServerOp for ListBucketsParams { // type Reply = ListBucketsReply; // async fn call(self, req: HttpRequest, api: &dyn ApiLayer) -> HttpResult { // let r = api.list_buckets(self).await?; // let mut w = BodyWriter::new_xml(); // w.append(""); // w.append(""); // for b in r.buckets { // w.append(""); // w.append_xml("Name", b.name.as_str()); // w.append_xml("CreationDate", "2021-09-19T00:00:00.000Z"); // w.append(""); // } // w.append(""); // w.append(""); // w.append_xml("ID", r.owner.id.as_str()); // w.append_xml("DisplayName", r.owner.display_name.as_str()); // w.append(""); // w.append(""); // Response::builder() // .status(StatusCode::OK) // .header("", "") // .body(w.body()) // } // } // #[async_trait] // impl BucketApiOp for GetBucketParams { // async fn call(self, api: &dyn BucketApiLayer) -> ApiRet { // api.get_bucket(self) // } // } // #[async_trait] // impl BucketApiOp for PutBucketParams { // async fn call(self, api: &dyn BucketApiLayer) -> ApiRet { // api.put_bucket(self) // } // } // #[async_trait] // impl BucketApiOp for DeleteBucketParams { // async fn call(self, api: &dyn BucketApiLayer) -> ApiRet { // api.delete_bucket(self) // } // } // pub trait ReqParser { // fn parse(req: HttpRequest, bucket: &str, key: &str) -> Self; // } // pub trait ResWriter { // fn write(self) -> HttpResponse; // } // pub trait RetWriter { // fn write(self) -> HttpResult; // } // impl RetWriter for ApiRet { // fn write(self) -> HttpResult { // match self { // Ok(res) => Ok(res.write()), // Err(err) => Ok(err.write()), // } // } // } impl From> for HttpResultOrErr { fn from(r: ApiRet) -> Self { match r { Ok(res) => Ok(res.into()), Err(err) => { let mut w = BodyWriter::new_xml(); let info = err.info(); w.append(""); w.append_xml("Code", info.code.as_str()); // w.append_xml("Message", info.msg.as_str()); // w.append_xml("Resource", info.resource.as_str()); // w.append_xml("RequestId", info.request_id.as_str()); w.append(""); let mut r = HttpResponse::new(w.body()); *r.status_mut() = info.status_code; r } } } } impl From<&HttpRequest> for ListBucketsParams { /// Request Syntax: /// ``` /// GET / HTTP/1.1 /// ``` fn from(_req: &HttpRequest) -> Self { Self {} } } impl From for HttpResultOrErr { /// Response Syntax: /// ``` /// HTTP/1.1 200 /// /// /// /// /// timestamp /// string /// /// /// /// string /// string /// /// /// ``` fn from(r: ListBucketsReply) -> Self { let mut w = BodyWriter::new_xml(); w.append(""); w.append(""); for b in r.buckets { w.append(""); w.append_xml("Name", b.name.as_str()); w.append_xml("CreationDate", "2021-09-19T00:00:00.000Z"); w.append(""); } w.append(""); w.append(""); w.append_xml("ID", r.owner.id.as_str()); w.append_xml("DisplayName", r.owner.display_name.as_str()); w.append(""); w.append(""); Ok(Response::builder() .status(StatusCode::OK) .header("", "") .body(w.body()) .unwrap()) } } // impl ReqParser for ListBucketsParams { // /// Request Syntax: // /// ``` // /// GET / HTTP/1.1 // /// ``` // fn parse(req: HttpRequest, _bucket: &str, _key: &str) -> Self { // let (parts, _) = req.into_parts(); // let params = Self {}; // Request::from_parts(parts, params) // } // } // impl ResWriter for ListBucketsReply { // /// Response Syntax: // /// ``` // /// HTTP/1.1 200 // /// // /// // /// // /// // /// timestamp // /// string // /// // /// // /// // /// string // /// string // /// // /// // /// ``` // fn write(self) -> HttpResponse { // let (parts, r) = self.into_parts(); // let mut w = BodyWriter::new_xml(); // w.append(""); // w.append(""); // for b in r.buckets { // w.append(""); // w.append_xml("Name", b.name.as_str()); // w.append_xml("CreationDate", "2021-09-19T00:00:00.000Z"); // w.append(""); // } // w.append(""); // w.append(""); // w.append_xml("ID", r.owner.id.as_str()); // w.append_xml("DisplayName", r.owner.display_name.as_str()); // w.append(""); // w.append(""); // Response::from_parts(parts, w.body()) // } // }