diff --git a/src/api/api_server.rs b/src/api/api_server.rs index a38a3c5..ea1990d 100644 --- a/src/api/api_server.rs +++ b/src/api/api_server.rs @@ -305,6 +305,7 @@ async fn handler_inner(garage: Arc, req: Request) -> Result { handle_delete_objects(garage, bucket_id, req, content_sha256).await } + Endpoint::GetBucketWebsite { .. } => handle_get_website(garage, bucket_id).await, Endpoint::PutBucketWebsite { .. } => { handle_put_website(garage, bucket_id, req, content_sha256).await } diff --git a/src/api/s3_website.rs b/src/api/s3_website.rs index 85d7c26..fcf8cba 100644 --- a/src/api/s3_website.rs +++ b/src/api/s3_website.rs @@ -11,9 +11,46 @@ use crate::signature::verify_signed_content; use garage_model::bucket_table::*; use garage_model::garage::Garage; use garage_table::*; -use garage_util::crdt; use garage_util::data::*; +pub async fn handle_get_website( + garage: Arc, + bucket_id: Uuid, +) -> Result, Error> { + let bucket = garage + .bucket_table + .get(&EmptyKey, &bucket_id) + .await? + .ok_or(Error::NoSuchBucket)?; + + let param = bucket + .params() + .ok_or_internal_error("Bucket should not be deleted at this point")?; + + if let Some(website) = param.website_config.get() { + let wc = WebsiteConfiguration { + xmlns: (), + error_document: website.error_document.as_ref().map(|v| Key { + key: Value(v.to_string()), + }), + index_document: Some(Suffix { + suffix: Value(website.index_document.to_string()), + }), + redirect_all_requests_to: None, + routing_rules: None, + }; + let xml = quick_xml::se::to_string(&wc)?; + Ok(Response::builder() + .status(StatusCode::OK) + .header(http::header::CONTENT_TYPE, "application/xml") + .body(Body::from(xml))?) + } else { + Ok(Response::builder() + .status(StatusCode::NO_CONTENT) + .body(Body::empty())?) + } +} + pub async fn handle_delete_website( garage: Arc, bucket_id: Uuid, @@ -24,17 +61,16 @@ pub async fn handle_delete_website( .await? .ok_or(Error::NoSuchBucket)?; - if let crdt::Deletable::Present(param) = &mut bucket.state { - param.website_config.update(None); - garage.bucket_table.insert(&bucket).await?; - } else { - unreachable!(); - } + let param = bucket + .params_mut() + .ok_or_internal_error("Bucket should not be deleted at this point")?; + + param.website_config.update(None); + garage.bucket_table.insert(&bucket).await?; Ok(Response::builder() .status(StatusCode::NO_CONTENT) - .body(Body::from(vec![])) - .unwrap()) + .body(Body::empty())?) } pub async fn handle_put_website( @@ -52,22 +88,21 @@ pub async fn handle_put_website( .await? .ok_or(Error::NoSuchBucket)?; + let param = bucket + .params_mut() + .ok_or_internal_error("Bucket should not be deleted at this point")?; + let conf: WebsiteConfiguration = from_reader(&body as &[u8])?; conf.validate()?; - if let crdt::Deletable::Present(param) = &mut bucket.state { - param - .website_config - .update(Some(conf.into_garage_website_config()?)); - garage.bucket_table.insert(&bucket).await?; - } else { - unreachable!(); - } + param + .website_config + .update(Some(conf.into_garage_website_config()?)); + garage.bucket_table.insert(&bucket).await?; Ok(Response::builder() .status(StatusCode::OK) - .body(Body::from(vec![])) - .unwrap()) + .body(Body::empty())?) } #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]