From af5f68a34d5ac51e6fae63d76f44dd2fa80def06 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Fri, 6 Mar 2026 12:26:17 +0100 Subject: [PATCH] admin api: allow updating website routing rules --- doc/api/garage-admin-v2.json | 9 ++++++ src/api/admin/api.rs | 2 ++ src/api/admin/bucket.rs | 24 ++++++++++++++-- src/api/common/xml/website.rs | 50 +++++++++++++++++---------------- src/garage/cli/remote/bucket.rs | 2 ++ 5 files changed, 60 insertions(+), 27 deletions(-) diff --git a/doc/api/garage-admin-v2.json b/doc/api/garage-admin-v2.json index c94825c4..3b5e66a3 100644 --- a/doc/api/garage-admin-v2.json +++ b/doc/api/garage-admin-v2.json @@ -4348,6 +4348,15 @@ "string", "null" ] + }, + "routingRules": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/components/schemas/website.RoutingRule" + } } } }, diff --git a/src/api/admin/api.rs b/src/api/admin/api.rs index 23f6d65b..8ffd6d0d 100644 --- a/src/api/admin/api.rs +++ b/src/api/admin/api.rs @@ -961,6 +961,8 @@ pub struct UpdateBucketWebsiteAccess { pub enabled: bool, pub index_document: Option, pub error_document: Option, + #[serde(default)] + pub routing_rules: Option>, } // ---- DeleteBucket ---- diff --git a/src/api/admin/bucket.rs b/src/api/admin/bucket.rs index 78146430..93766c7b 100644 --- a/src/api/admin/bucket.rs +++ b/src/api/admin/bucket.rs @@ -294,10 +294,28 @@ impl RequestHandler for UpdateBucketRequest { if let Some(wa) = self.body.website_access { if wa.enabled { - let (redirect_all, routing_rules) = match state.website_config.get() { - Some(wc) => (wc.redirect_all.clone(), wc.routing_rules.clone()), - None => (None, Vec::new()), + let redirect_all = state + .website_config + .get() + .as_ref() + .and_then(|wc| wc.redirect_all.clone()); + + let routing_rules = if let Some(rr) = wa.routing_rules { + for r in rr.iter() { + r.validate()?; + } + rr.into_iter() + .map(xml::website::RoutingRule::into_garage_routing_rule) + .collect::>() + } else { + state + .website_config + .get() + .as_ref() + .map(|wc| wc.routing_rules.clone()) + .unwrap_or_default() }; + state.website_config.update(Some(WebsiteConfig { index_document: wa.index_document.ok_or_bad_request( "Please specify indexDocument when enabling website access.", diff --git a/src/api/common/xml/website.rs b/src/api/common/xml/website.rs index 7759aa2c..a3889cda 100644 --- a/src/api/common/xml/website.rs +++ b/src/api/common/xml/website.rs @@ -149,30 +149,7 @@ impl WebsiteConfiguration { .routing_rules .rules .into_iter() - .map(|rule| { - bucket_table::RoutingRule { - condition: rule.condition.map(|condition| { - bucket_table::RedirectCondition { - http_error_code: condition.http_error_code.map(|c| c.0 as u16), - prefix: condition.prefix.map(|p| p.0), - } - }), - redirect: bucket_table::Redirect { - hostname: rule.redirect.hostname.map(|h| h.0), - protocol: rule.redirect.protocol.map(|p| p.0), - // aws default to 301, which i find punitive in case of - // misconfiguration (can be permanently cached on the - // user agent) - http_redirect_code: rule - .redirect - .http_redirect_code - .map(|c| c.0 as u16) - .unwrap_or(302), - replace_key_prefix: rule.redirect.replace_prefix.map(|k| k.0), - replace_key: rule.redirect.replace_full.map(|k| k.0), - }, - } - }) + .map(RoutingRule::into_garage_routing_rule) .collect(), }) } @@ -237,6 +214,31 @@ impl RoutingRule { }, } } + + pub fn into_garage_routing_rule(self) -> bucket_table::RoutingRule { + bucket_table::RoutingRule { + condition: self + .condition + .map(|condition| bucket_table::RedirectCondition { + http_error_code: condition.http_error_code.map(|c| c.0 as u16), + prefix: condition.prefix.map(|p| p.0), + }), + redirect: bucket_table::Redirect { + hostname: self.redirect.hostname.map(|h| h.0), + protocol: self.redirect.protocol.map(|p| p.0), + // aws default to 301, which i find punitive in case of + // misconfiguration (can be permanently cached on the + // user agent) + http_redirect_code: self + .redirect + .http_redirect_code + .map(|c| c.0 as u16) + .unwrap_or(302), + replace_key_prefix: self.redirect.replace_prefix.map(|k| k.0), + replace_key: self.redirect.replace_full.map(|k| k.0), + }, + } + } } impl Condition { diff --git a/src/garage/cli/remote/bucket.rs b/src/garage/cli/remote/bucket.rs index 64272d11..edfeaca5 100644 --- a/src/garage/cli/remote/bucket.rs +++ b/src/garage/cli/remote/bucket.rs @@ -309,12 +309,14 @@ impl Cli { error_document: opt .error_document .or_else(|| bucket_website_config.and_then(|x| x.error_document.clone())), + routing_rules: None, } } else { UpdateBucketWebsiteAccess { enabled: false, index_document: None, error_document: None, + routing_rules: None, } };