amazonka
amazonka copied to clipboard
Can't add "Content-Length" header to presigned PUT URL
I'm trying to enforce file size limits on presigned PUTs as per the top answer on this post: https://stackoverflow.com/questions/25991275/limit-size-of-objects-while-uploading-to-amazon-s3-using-pre-signed-url
However, the following code results in a presigned URL that does not contain the signed header "Content-Length":
import ClassyPrelude
import Amazonka.Presign (presignWithHeaders, defaultHeaders)
import Network.URI ( uriToString )
presignWithContentLength auth envOverride' = do
let headers = defaultHeaders . (<> [("Content-Length", "10000000")]
presignedRequest <- presignWithHeaders headers envOverride' auth (region config) now 120 (newPutObject (BucketName bucketName) (ObjectKey objKey) (toBody ("" :: ByteString)))
let result = (uriToString id $ getUri presignedRequest) ""
pure $ toText result
Am I doing something wrong?
For next time, please upload a minimal reproduction that compiles. I had to wrangle a fair bit by hand to get everything set up.
It looks like the Content-Length
header is explicitly deleted when headers are normalised:
https://github.com/brendanhay/amazonka/blob/098795f847df7239af64535c6b2b233f3fbd699c/lib/amazonka-core/src/Amazonka/Sign/V4/Base.hs#L290
This appears to have initially been done in a3eabd987287bd5117faa07cb2875bad2ed9ae21 because you're not allowed to send content-length
when using SigV4 streaming signatures (to S3).
I don't plan to fix this anytime soon. Updating to latest botocore and generating new service bindings are higher priority, but if you'd like to try I think the trick will be to parameterise signMetadata
in Amazonka.Sign.V4.Base
so that we can differentiate between signing metadata for a chunked body, for a hashed body, or for a presign. A three-valued enum data SigningType = Presign | HashedBody | ChunkedBody
is probably the way to go.
Ah, sorry about that.
Thanks for the info--I'll look into your solution.
I will have bandwidth to look at and merge a PR, so let me know if you do give this a go.
If I'm able to, it won't be for several weeks at minimum. Startup life :)