Checking S3 compatibility for MIME types for presigned POST urls

Hi there,

I am using presigned POST urls to upload files to Tigris buckets. To set the correct MIME type, I add the MIME type in the Content-Type header during the file upload request. This seems to work without explicitly specifying the content-type in the presigned url.

  1. Does this work for any MIME type?

I am asking this because when I include the Content-Type in the signing process like X-Amz-SignedHeaders=content-type;host with the MIME defined in the canonical part, then I get an Signature does not match error during the upload request.

So my second question:

  1. Is this a mistake on my part or is Tigris not yet compatiple with this S3 feature?

Thanks in advance.

Hello @hakoptak

Can you share your client code that generates pre-signed URL accounting the Content-Type.

Thanks!
Jigar

Hi @jmj, thanks for following up. Just to let you know that I am preparing a detailed response, but that I’m a bit short on time at this moment. I’ll keep this thread open in the meanwhile.

By the way: I did spot a tiny mistake/ambiguity in the documentation about presigning. It says:

… and generated URL would look like:

https://t3.storage.dev/mybucket.mydomain.com/hello.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=tid_

This should be:

https://fly.storage.tigris.dev/mybucket.mydomain.com/hello.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=tid_

I’ll try to answer this tomorrow.

Hi @jmj, I’m using the same code as shared in this post, except that:

// Add parameters in the correct order
canonicalQueryString.WriteString(fmt.Sprintf("X-Amz-Algorithm=%s", algorithm))
canonicalQueryString.WriteString(fmt.Sprintf("&X-Amz-Credential=%s", credential.String()))
canonicalQueryString.WriteString(fmt.Sprintf("&X-Amz-Date=%s", dateTime))
canonicalQueryString.WriteString(fmt.Sprintf("&X-Amz-Expires=%d", int(p.Expiration.Seconds())))
canonicalQueryString.WriteString("&X-Amz-SignedHeaders=content-type;host")

// Build host and canonical headers
var canonicalHeaders strings.Builder

canonicalHeaders.WriteString(fmt.Sprintf("content-type:%s", mime))
canonicalHeaders.WriteByte('\n')
canonicalHeaders.WriteString(fmt.Sprintf("host:%s", p.Endpoint))
canonicalHeaders.WriteByte('\n')

// Build canonical request
var canonicalRequest strings.Builder

canonicalRequest.WriteString(p.Method)
canonicalRequest.WriteByte('\n')
canonicalRequest.WriteString(canonicalURI.String())
canonicalRequest.WriteByte('\n')
canonicalRequest.WriteString(canonicalQueryString.String())
canonicalRequest.WriteByte('\n')
canonicalRequest.WriteString(canonicalHeaders.String())
canonicalRequest.WriteByte('\n')
canonicalRequest.WriteString("content-type;host")
canonicalRequest.WriteByte('\n')
canonicalRequest.WriteString("UNSIGNED-PAYLOAD")

The client then generates the following url:

https://test.sessions.pinggg.cloud/7s8g5fgphySq7gc07POSts74eDDfoO77q61BcJUQOCCA/shares/1.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=tid_mNpmYFuMLHfstgsbJEnjDXQLjRSgqXlznLCJdlY_ZIhereWHco%2F20250627%2Fauto%2Fs3%2Faws4_request&X-Amz-Date=20250627T180046Z&X-Amz-Expires=15&X-Amz-SignedHeaders=content-type;host&X-Amz-Signature=e58ac8dc263db97f06795cc46ac5fa0bb1aaeb2952b1eb66f8beb7ef7a5139fc

But during upload I get the message (400 Bad Request):

<Error>
<Code>AuthorizationQueryParametersError</Code>
<Message>Query-string authentication version 4 requires the X-Amz-Algorithm, X-Amz-Credential, X-Amz-Signature, X-Amz-Date, X-Amz-SignedHeaders, and X-Amz-Expires parameters.</Message>
<Resource>/7s8g5fgphySq7gc07POSts74eDDfoO77q61BcJUQOCCA/shares/1.png</Resource>
<RequestId>1751047264049587309</RequestId>
<Key>7s8g5fgphySq7gc07POSts74eDDfoO77q61BcJUQOCCA/shares/1.png</Key>
<BucketName>test.sessions.pinggg.cloud</BucketName>
</Error>

When I don’t include the content type in the signing process then it works fine.

For now I leave out the content type… and put my focus back on building my product :wink:

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.