aboutsummaryrefslogtreecommitdiff
path: root/src/api
diff options
context:
space:
mode:
Diffstat (limited to 'src/api')
-rw-r--r--src/api/s3/copy.rs4
-rw-r--r--src/api/s3/lib.rs2
-rw-r--r--src/api/s3/multipart.rs2
-rw-r--r--src/api/s3/post_object.rs4
-rw-r--r--src/api/s3/put.rs19
-rw-r--r--src/api/s3/website.rs5
6 files changed, 27 insertions, 9 deletions
diff --git a/src/api/s3/copy.rs b/src/api/s3/copy.rs
index 9ae48807..ff8019e6 100644
--- a/src/api/s3/copy.rs
+++ b/src/api/s3/copy.rs
@@ -28,7 +28,7 @@ use crate::encryption::EncryptionParams;
use crate::error::*;
use crate::get::full_object_byte_stream;
use crate::multipart;
-use crate::put::{get_headers, save_stream, ChecksumMode, SaveStreamResult};
+use crate::put::{extract_metadata_headers, save_stream, ChecksumMode, SaveStreamResult};
use crate::xml::{self as s3_xml, xmlns_tag};
// -------- CopyObject ---------
@@ -73,7 +73,7 @@ pub async fn handle_copy(
let dest_object_meta = ObjectVersionMetaInner {
headers: match req.headers().get("x-amz-metadata-directive") {
Some(v) if v == hyper::header::HeaderValue::from_static("REPLACE") => {
- get_headers(req.headers())?
+ extract_metadata_headers(req.headers())?
}
_ => source_object_meta_inner.into_owned().headers,
},
diff --git a/src/api/s3/lib.rs b/src/api/s3/lib.rs
index 4d1d3ef5..83f684f8 100644
--- a/src/api/s3/lib.rs
+++ b/src/api/s3/lib.rs
@@ -14,7 +14,7 @@ mod list;
mod multipart;
mod post_object;
mod put;
-mod website;
+pub mod website;
mod encryption;
mod router;
diff --git a/src/api/s3/multipart.rs b/src/api/s3/multipart.rs
index 1ee04bc1..d6eb26cb 100644
--- a/src/api/s3/multipart.rs
+++ b/src/api/s3/multipart.rs
@@ -49,7 +49,7 @@ pub async fn handle_create_multipart_upload(
let upload_id = gen_uuid();
let timestamp = next_timestamp(existing_object.as_ref());
- let headers = get_headers(req.headers())?;
+ let headers = extract_metadata_headers(req.headers())?;
let meta = ObjectVersionMetaInner {
headers,
checksum: None,
diff --git a/src/api/s3/post_object.rs b/src/api/s3/post_object.rs
index 350684da..b9bccae6 100644
--- a/src/api/s3/post_object.rs
+++ b/src/api/s3/post_object.rs
@@ -24,7 +24,7 @@ use garage_api_common::signature::payload::{verify_v4, Authorization};
use crate::api_server::ResBody;
use crate::encryption::EncryptionParams;
use crate::error::*;
-use crate::put::{get_headers, save_stream, ChecksumMode};
+use crate::put::{extract_metadata_headers, save_stream, ChecksumMode};
use crate::xml as s3_xml;
pub async fn handle_post_object(
@@ -216,7 +216,7 @@ pub async fn handle_post_object(
// if we ever start supporting ACLs, we likely want to map "acl" to x-amz-acl" somewhere
// around here to make sure the rest of the machinery takes our acl into account.
- let headers = get_headers(&params)?;
+ let headers = extract_metadata_headers(&params)?;
let checksum_algorithm = request_checksum_algorithm(&params)?;
let expected_checksums = ExpectedChecksums {
diff --git a/src/api/s3/put.rs b/src/api/s3/put.rs
index 4d866a06..830a7998 100644
--- a/src/api/s3/put.rs
+++ b/src/api/s3/put.rs
@@ -37,6 +37,7 @@ use garage_api_common::signature::checksum::*;
use crate::api_server::{ReqBody, ResBody};
use crate::encryption::EncryptionParams;
use crate::error::*;
+use crate::website::X_AMZ_WEBSITE_REDIRECT_LOCATION;
const PUT_BLOCKS_MAX_PARALLEL: usize = 3;
@@ -62,7 +63,7 @@ pub async fn handle_put(
key: &String,
) -> Result<Response<ResBody>, Error> {
// Retrieve interesting headers from request
- let headers = get_headers(req.headers())?;
+ let headers = extract_metadata_headers(req.headers())?;
debug!("Object headers: {:?}", headers);
let expected_checksums = ExpectedChecksums {
@@ -649,7 +650,9 @@ impl Drop for InterruptedCleanup {
// ============ helpers ============
-pub(crate) fn get_headers(headers: &HeaderMap<HeaderValue>) -> Result<HeaderList, Error> {
+pub(crate) fn extract_metadata_headers(
+ headers: &HeaderMap<HeaderValue>,
+) -> Result<HeaderList, Error> {
let mut ret = Vec::new();
// Preserve standard headers
@@ -675,6 +678,18 @@ pub(crate) fn get_headers(headers: &HeaderMap<HeaderValue>) -> Result<HeaderList
std::str::from_utf8(value.as_bytes())?.to_string(),
));
}
+ if name == X_AMZ_WEBSITE_REDIRECT_LOCATION {
+ let value = std::str::from_utf8(value.as_bytes())?.to_string();
+ if !(value.starts_with("/")
+ || value.starts_with("http://")
+ || value.starts_with("https://"))
+ {
+ return Err(Error::bad_request(format!(
+ "Invalid {X_AMZ_WEBSITE_REDIRECT_LOCATION} header",
+ )));
+ }
+ ret.push((X_AMZ_WEBSITE_REDIRECT_LOCATION.to_string(), value));
+ }
}
Ok(ret)
diff --git a/src/api/s3/website.rs b/src/api/s3/website.rs
index 7553bef7..03cc01d8 100644
--- a/src/api/s3/website.rs
+++ b/src/api/s3/website.rs
@@ -1,6 +1,6 @@
use quick_xml::de::from_reader;
-use hyper::{Request, Response, StatusCode};
+use hyper::{header::HeaderName, Request, Response, StatusCode};
use serde::{Deserialize, Serialize};
use garage_model::bucket_table::*;
@@ -11,6 +11,9 @@ use crate::api_server::{ReqBody, ResBody};
use crate::error::*;
use crate::xml::{to_xml_with_header, xmlns_tag, IntValue, Value};
+pub const X_AMZ_WEBSITE_REDIRECT_LOCATION: HeaderName =
+ HeaderName::from_static("x-amz-website-redirect-location");
+
pub async fn handle_get_website(ctx: ReqCtx) -> Result<Response<ResBody>, Error> {
let ReqCtx { bucket_params, .. } = ctx;
if let Some(website) = bucket_params.website_config.get() {