aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/api/s3/get.rs44
-rw-r--r--src/web/web_server.rs83
2 files changed, 73 insertions, 54 deletions
diff --git a/src/api/s3/get.rs b/src/api/s3/get.rs
index eea3434e..f5d3cf11 100644
--- a/src/api/s3/get.rs
+++ b/src/api/s3/get.rs
@@ -163,15 +163,7 @@ pub async fn handle_head(
key: &str,
part_number: Option<u64>,
) -> Result<Response<ResBody>, Error> {
- handle_head_without_ctx(
- ctx.garage,
- req,
- ctx.bucket_id,
- key,
- StatusCode::OK,
- part_number,
- )
- .await
+ handle_head_without_ctx(ctx.garage, req, ctx.bucket_id, key, part_number).await
}
/// Handle HEAD request for website
@@ -180,7 +172,6 @@ pub async fn handle_head_without_ctx(
req: &Request<impl Body>,
bucket_id: Uuid,
key: &str,
- status_code: StatusCode,
part_number: Option<u64>,
) -> Result<Response<ResBody>, Error> {
let object = garage
@@ -281,7 +272,7 @@ pub async fn handle_head_without_ctx(
checksum_mode,
)
.header(CONTENT_LENGTH, format!("{}", version_meta.size))
- .status(status_code)
+ .status(StatusCode::OK)
.body(empty_body())?)
}
}
@@ -294,16 +285,7 @@ pub async fn handle_get(
part_number: Option<u64>,
overrides: GetObjectOverrides,
) -> Result<Response<ResBody>, Error> {
- handle_get_without_ctx(
- ctx.garage,
- req,
- ctx.bucket_id,
- key,
- StatusCode::OK,
- part_number,
- overrides,
- )
- .await
+ handle_get_without_ctx(ctx.garage, req, ctx.bucket_id, key, part_number, overrides).await
}
/// Handle GET request
@@ -312,7 +294,6 @@ pub async fn handle_get_without_ctx(
req: &Request<impl Body>,
bucket_id: Uuid,
key: &str,
- status_code: StatusCode,
part_number: Option<u64>,
overrides: GetObjectOverrides,
) -> Result<Response<ResBody>, Error> {
@@ -348,15 +329,11 @@ pub async fn handle_get_without_ctx(
let checksum_mode = checksum_mode(&req);
- match (
- part_number,
- parse_range_header(req, last_v_meta.size)?,
- status_code == StatusCode::OK,
- ) {
- (Some(_), Some(_), _) => Err(Error::bad_request(
+ match (part_number, parse_range_header(req, last_v_meta.size)?) {
+ (Some(_), Some(_)) => Err(Error::bad_request(
"Cannot specify both partNumber and Range header",
)),
- (Some(pn), None, true) => {
+ (Some(pn), None) => {
handle_get_part(
garage,
last_v,
@@ -369,7 +346,7 @@ pub async fn handle_get_without_ctx(
)
.await
}
- (None, Some(range), true) => {
+ (None, Some(range)) => {
handle_get_range(
garage,
last_v,
@@ -383,8 +360,7 @@ pub async fn handle_get_without_ctx(
)
.await
}
- _ => {
- // either not a range, or an error request: always return the full doc
+ (None, None) => {
handle_get_full(
garage,
last_v,
@@ -394,7 +370,6 @@ pub async fn handle_get_without_ctx(
&headers,
overrides,
checksum_mode,
- status_code,
)
.await
}
@@ -410,7 +385,6 @@ async fn handle_get_full(
meta_inner: &ObjectVersionMetaInner,
overrides: GetObjectOverrides,
checksum_mode: ChecksumMode,
- status_code: StatusCode,
) -> Result<Response<ResBody>, Error> {
let mut resp_builder = object_headers(
version,
@@ -420,7 +394,7 @@ async fn handle_get_full(
checksum_mode,
)
.header(CONTENT_LENGTH, format!("{}", version_meta.size))
- .status(status_code);
+ .status(StatusCode::OK);
getobject_override_headers(overrides, &mut resp_builder)?;
let stream = full_object_byte_stream(garage, version, version_data, encryption);
diff --git a/src/web/web_server.rs b/src/web/web_server.rs
index bd543bb0..23a21614 100644
--- a/src/web/web_server.rs
+++ b/src/web/web_server.rs
@@ -6,6 +6,7 @@ use tokio::net::{TcpListener, UnixListener};
use tokio::sync::watch;
use hyper::{
+ body::Body,
body::Incoming as IncomingBody,
header::{HeaderValue, HOST},
Method, Request, Response, StatusCode,
@@ -22,6 +23,7 @@ use crate::error::*;
use garage_api::generic_server::{server_loop, UnixListenerOn};
use garage_api::helpers::*;
+use garage_api::s3::api_server::ResBody;
use garage_api::s3::cors::{add_cors_headers, find_matching_cors_rule, handle_options_for_bucket};
use garage_api::s3::error::{
CommonErrorDerivative, Error as ApiError, OkOrBadRequest, OkOrInternalError,
@@ -252,19 +254,10 @@ impl WebServer {
.body(empty_body())
.unwrap()),
(&Method::HEAD, Ok((key, code))) => {
- handle_head_without_ctx(self.garage.clone(), req, bucket_id, key, code, None).await
+ handle_head(self.garage.clone(), req, bucket_id, key, code).await
}
(&Method::GET, Ok((key, code))) => {
- handle_get_without_ctx(
- self.garage.clone(),
- req,
- bucket_id,
- key,
- code,
- None,
- Default::default(),
- )
- .await
+ handle_get(self.garage.clone(), req, bucket_id, key, code).await
}
_ => Err(ApiError::bad_request("HTTP method not supported")),
};
@@ -306,25 +299,22 @@ impl WebServer {
) => {
match *req.method() {
Method::HEAD => {
- handle_head_without_ctx(
+ handle_head(
self.garage.clone(),
req,
bucket_id,
redirect_key,
*redirect_code,
- None,
)
.await
}
Method::GET => {
- handle_get_without_ctx(
+ handle_get(
self.garage.clone(),
req,
bucket_id,
redirect_key,
*redirect_code,
- None,
- Default::default(),
)
.await
}
@@ -361,14 +351,12 @@ impl WebServer {
.body(empty_body::<Infallible>())
.unwrap();
- match handle_get_without_ctx(
+ match handle_get(
self.garage.clone(),
&req2,
bucket_id,
&error_document,
error.http_status_code(),
- None,
- Default::default(),
)
.await
{
@@ -413,6 +401,63 @@ impl WebServer {
}
}
+async fn handle_head(
+ garage: Arc<Garage>,
+ req: &Request<impl Body>,
+ bucket_id: Uuid,
+ key: &str,
+ status_code: StatusCode,
+) -> Result<Response<ResBody>, ApiError> {
+ if status_code != StatusCode::OK {
+ // See comment in handle_get
+ let cleaned_req = Request::builder()
+ .uri(req.uri())
+ .body(empty_body::<Infallible>())
+ .unwrap();
+
+ let mut ret = handle_head_without_ctx(garage, &cleaned_req, bucket_id, key, None).await?;
+ *ret.status_mut() = status_code;
+ Ok(ret)
+ } else {
+ handle_head_without_ctx(garage, req, bucket_id, key, None).await
+ }
+}
+
+pub async fn handle_get(
+ garage: Arc<Garage>,
+ req: &Request<impl Body>,
+ bucket_id: Uuid,
+ key: &str,
+ status_code: StatusCode,
+) -> Result<Response<ResBody>, ApiError> {
+ if status_code != StatusCode::OK {
+ // If we are returning an error document, discard all headers from
+ // the original GET request that would have influenced the result:
+ // - Range header, we don't want to return a subrange of the error document
+ // - Caching directives such as If-None-Match, etc, which are not relevant
+ let cleaned_req = Request::builder()
+ .uri(req.uri())
+ .body(empty_body::<Infallible>())
+ .unwrap();
+
+ let mut ret = handle_get_without_ctx(
+ garage,
+ &cleaned_req,
+ bucket_id,
+ key,
+ None,
+ Default::default(),
+ )
+ .await?;
+
+ *ret.status_mut() = status_code;
+
+ Ok(ret)
+ } else {
+ handle_get_without_ctx(garage, req, bucket_id, key, None, Default::default()).await
+ }
+}
+
fn error_to_res(e: Error) -> Response<BoxBody<Error>> {
// If we are here, it is either that:
// - there was an error before trying to get the requested URL