Support for PostObject #222
No reviewers
Labels
No labels
action
check-aws
action
discussion-needed
action
for-external-contributors
action
for-newcomers
action
more-info-needed
action
need-funding
action
triage-required
kind
correctness
kind
ideas
kind
improvement
kind
performance
kind
testing
kind
usability
kind
wrong-behavior
prio
critical
prio
low
scope
admin-api
scope
background-healing
scope
build
scope
documentation
scope
k8s
scope
layout
scope
metadata
scope
ops
scope
rpc
scope
s3-api
scope
security
scope
telemetry
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: Deuxfleurs/garage#222
Loading…
Reference in a new issue
No description provided.
Delete branch "trinity-1686a/garage:post-object"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Add support for PostObject
Todo/done:
569f7496ae
to73d234c893
30e8e885a5
to6a42cd027e
6a42cd027e
to853e18bd44
15fdbb48e2
to11bb514b34
@ -0,0 +217,4 @@
.status(StatusCode::OK)
.body(Body::empty())?,
"201" => {
// TODO body should be an XML document, not sure which yet
the actual response should be
with corresponding
etag
andlocation
http headers (these headers are also here for 200 and 204, but not the body)When using
success_action_redirect
,etag
is set as usual, and location is set to${success_action_redirect}?bucket=bucketname&key=key&etag=%220123456789abcdef0123456789abcdef%22
4f52708111
tof551062456
WIP: Support for PostObjectto Support for PostObject@ -0,0 +43,4 @@
let mut multipart = Multipart::with_constraints(body, boundary, constraints);
let mut params = HeaderMap::new();
while let Some(field) = multipart.next_field().await? {
I think we can avoid putting almost the entire code of this function in the
while
loop (and remove 1 indentation level almost everywhere) by doing something like this:This looks much nicer to me, especially as in the current version we have a
for
inside thewhile
, which looks a bit like a nested loop but is in fact not at all.@ -0,0 +235,4 @@
.and_then(|h| h.to_str().ok())
.unwrap_or("204");
let builder = Response::builder()
.status(StatusCode::OK)
Looks like we don't need this
.status()
as we are calling it in all branches belowe5d1856f17
to46c769ca00
f1ebcad654
to16cd481d1a
I feel like there are a few things concerning policy validation that require clarification.
For the unit test I will write it and put it in the comment so that you can just paste it in your code.
@ -0,0 +111,4 @@
if let Some(filename) = field.file_name() {
key.replace("${filename}", filename)
} else {
key.to_owned()
This looks like it should rather be an error case: if the application builder put
${filename}
in the key field but the browser for some reason didn't include the name of the uploaded file, we probably want to reject the request.that was actually how a previous iteration worked. This behavior was added because it's exactly how AWS behave (not that I can say I agree with that behavior)
:/
@ -0,0 +141,4 @@
));
}
let mut conditions = decoded_policy.into_conditions()?;
I feel like we should add unit tests for the policy decoding logic (not just for into_conditions but end-to-end starting with JSON)
I'll write a test and post it in the comments of the PR so that you can copy and paste
@ -0,0 +167,4 @@
"key" => {
let conds = conditions.params.remove("key").ok_or_else(|| {
Error::BadRequest(format!("Key '{}' is not allowed in policy", param_key))
})?;
Can you point me to the documentation section which says that there must be a policy specified for the
key
field?this is not specified, it's however the behavior of AWS.policy
andx-amz-signature
are the only two fields I found to not be required in the policy. Evenx-amz-credential
, which is definitelly required to make a valid v4 signature, must be allowed in policythis is in fact specified somewhere
Which means I have to add some code to ignore
x-ignore-*
, others are already ignored@ -0,0 +184,4 @@
_ => {
let conds = conditions.params.remove(¶m_key).ok_or_else(|| {
Error::BadRequest(format!("Key '{}' is not allowed in policy", param_key))
})?;
Same here, can you point me to the doc which says a policy must be given for all fields?
see comment on
key
@ -0,0 +216,4 @@
.ok_or_bad_request("Invalid content type")?
.unwrap_or_else(|| HeaderValue::from_static("blob"));
params.append(header::CONTENT_TYPE, content_type);
This definitely looks like it should have been done before the policy check
turns out AWS ignore this, and only consider content type set in what I called param, not in the field metadata
@ -0,0 +384,4 @@
struct Conditions {
params: HashMap<String, Vec<Operation>>,
content_type: Vec<Operation>,
Why do we need content_type to be set apart here? If it has different treatment I think that's applied at a later moment when we check the set of headers against the policy, here it could just be added to the map with the rest (the same that is done with
key
).Here are some simple tests for policy decoding (they require adding
#[derive(Debug)]
toOperation
):fe9cedfdf5
toa19079ba1a
a19079ba1a
to0fae509b29
0fae509b29
to3536903a58
3536903a58
tocea91e7a7d
cea91e7a7d
to32864bb8f3
LGTM