#6548·uppy

@uppy/aws-s3 v6: signRequest cannot supply headers required by a presigned URL

Author: milkcocoaCreated Sep 9, 2026Updated Sep 15, 2026
LabelsAWS S3

Initial checklist

  • I understand this is a bug report and questions should be posted in the Community Forum.
  • I searched existing issues and could not find a report covering this case.

Steps to reproduce

Version: @uppy/aws-s3 6.1.0, using signRequest for a direct, single-part PUT upload.

A signing endpoint can generate a presigned PutObject URL with both Content-Type and Content-Disposition included in the signature. For example, using the AWS SDK for Ruby:

ruby
url = Aws::S3::Presigner.new(client: s3_client).presigned_url(
  :put_object,
  bucket: "my-bucket",
  key: "uploads/example.pdf",
  content_type: "application/pdf",
  content_disposition: 'inline; filename="example.pdf"',
  expires_in: 300
)

The locally generated URL includes:

X-Amz-SignedHeaders=content-disposition;content-type;host

Return that URL and its required headers from the signing endpoint:

javascript
{
  url: "<presigned PUT URL>",
  key: "uploads/example.pdf",
  headers: {
    "Content-Type": "application/pdf",
    "Content-Disposition": 'inline; filename="example.pdf"',
  },
}

Configure Uppy to use the response:

javascript
import Uppy from '@uppy/core';
import AwsS3 from '@uppy/aws-s3';

const uppy = new Uppy().use(AwsS3, {
  shouldUseMultipart: false,
  async signRequest(request) {
    const response = await fetch('/uploads/sign', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(request),
    });
    if (!response.ok) throw new Error('Signing failed');
    return response.json();
  },
});

uppy.addFile({
  name: 'example.pdf',
  type: 'application/pdf',
  data: new File(['test upload'], 'example.pdf', {
    type: 'application/pdf',
  }),
});

await uppy.upload();

The file contents are arbitrary here; the issue concerns the signed request headers.

Expected behavior

A supported way to send the additional headers required by the presigned request. In v5, getUploadParameters could return upload headers.

For example, signRequest could accept a response shaped like { url, key?, headers? } and forward those headers to the S3 request, with defined handling for its internally generated Content-Type header.

Actual behavior

In the 6.1.0 source, S3mini.request() only reads url and key from the signing response. S3Client.xhr() sets Content-Type internally but does not receive additional headers. Returning headers from the signing endpoint therefore does not forward Content-Disposition to S3.

This prevents using the presigned request as issued. AWS requires the signed headers to match the headers sent by the client, so omitting Content-Disposition should result in signature validation failure. See AWS guidance on presigned URL signature mismatches.

Verification so far: source inspection and local URL generation with the AWS SDK for Ruby. I have not yet run an end-to-end reproduction against S3; the signature failure above is the expected consequence, not an observed S3 response.