Fix issue presigning request with custom headers, also fix small deviation from spec related to lower case headers #35
+100
−29
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Problem description
I found a problem related to adding custom signed headers. The header I want to sign is the
Content-Length, this is to ensure no one uploads over whatever limit I set from the backend.When trying to upload to Cloudflare R2 I get
I have cross-tested this against the PresignHTTP function provided in "github.com/aws/aws-sdk-go-v2/aws/signer/v4", and this produces a valid URL when the custom header is specified.
Fix part 1:
The fix here is to always URI encode the
extraheaders, that is remove the if condition here:I struggled to find anywhere in the spec that declared that value of
X-Amz-SignedHeadersshould be aws-uri-encoded, but it doesn't say anywhere that it shouldn't. So I dug through the AWS SDK source code (line 185), I see that they unconditionally do the aws-uri-encoding on all headers. So I suggest we just do the same. It makes the code a little bit easier after all.Difficulty testing
I wrote a new integration test trying to test this aginst the local Minio instance but it just failed. After som reading around I conclude that Minio just doesn't handle custom signed headers very well? Anyways, so I tested it against my Cloudflare R2 storage, and it works perfectly.
This implies that you have to setup other AWS credentials to test it, I just put in under a guard:
Assuming you have setup AWS env vars to something that isn't Minio, you can do:
TEST_REAL_S3=true go test -v -run 'TestS3_GeneratePresignedURL_ExtraHeader'to run the integration test.Other than that, the whole test suite passes as before 😄
Fix part 2:
When looking into this I uncovered a deviation from the spec that states:
So I just added that as well.