Question

Can I upload to Spaces using a signed url?

Hello,

Im currently developing a React webapp that lets users upload images. I have it working with AWS S3 but would like to have everything on DO for simplicities sake.

The flow goes like this:

  • Send image info to server and receive a signed url
  • Post the image to the signed url

When i try this with spaces im constantly getting a “SignatureDoesNotMatch” error.

Please help, im going batty!

Here’s my node server code:

spacesEndpoint = new aws.Endpoint(`${DO_REGION}.digitaloceanspaces.com`),
s3 = new aws.S3({
	endpoint: spacesEndpoint,
	accessKeyId: DO_ACCESS_KEY_ID,
	secretAccessKey: DO_SECRET_ACCESS_KEY,
	region: DO_REGION,
	signatureVersion: 'v4',
});

const s3Params = {
	Bucket: DO_SPACE,
	Expires: 60,
	Key: filePath,
	ContentType: fileType, // "image/jpeg"
	ACL: 'public-read',
};

const promise = new Promise((resolve, reject) => {
	s3.getSignedUrl('putObject', s3Params, (err, url) => {
		if (err) {
			reject(err);
		}
		resolve(url);
	});
});

and this is my javascript

const xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.open('PUT', payload.signedUrl);
xhr.setRequestHeader('Host', `${DO_SPACE}.${DO_REGION}.digitaloceanspaces.com');
xhr.setRequestHeader('x-amz-acl', 'public-read');
xhr.setRequestHeader('Content-Type', payload.file.type);
xhr.setRequestHeader('Content-Length', payload.file.size);
xhr.send(payload.file);

Submit an answer

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Sign In or Sign Up to Answer

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

Want to learn more? Join the DigitalOcean Community!

Join our DigitalOcean community of over a million developers for free! Get help and share knowledge in Q&A, subscribe to topics of interest, and get courses and tools that will help you grow as a developer and scale your project or business.

Hello

So i was able to get it workign with the CORS configuration you recommended, and the following server and client code.

Thank you very much for your help.

const aws = require('aws-sdk');
spacesEndpoint = new aws.Endpoint(`${DO_REGION}.digitaloceanspaces.com`),
s3 = new aws.S3({
	endpoint: spacesEndpoint,
	accessKeyId: DO_ACCESS_KEY_ID,
	secretAccessKey: DO_SECRET_ACCESS_KEY,
	region: DO_REGION,
	signatureVersion: 'v4',
});

const s3Params = {
	Bucket: DO_SPACE,
	Key: filePath,
	ContentType: fileType,
	ACL: 'public-read',
	Expires: 60,
};

s3.getSignedUrl('putObject', s3Params, (err, url) => {
	if (err) {
		reject(err);
	}

	resolve(url);
});
const xhr = new XMLHttpRequest();
xhr.open('PUT', signedUrl);
xhr.setRequestHeader('Content-Type', file.type);
xhr.setRequestHeader('x-amz-acl', 'public-read');
xhr.send(file);

@admin94a05aa0b9579d1a73a36 did this help? wanted to check if you made any progress.

OPTIONS is the HTTP method used for the CORS preflight request, to ask which other methods are permitted, based on the Access-Control-*, Origin headers that are sent, which are checked against the stores CORSConfiguration for a matching CORSRule.

A good group of settings for a single CORSRule during development:

  • Allowed Origin: *
  • AllowedMethod: (all of them)
  • AllowedHeader: * (important in dev, extra headers in SDKs can cause CORS preflight to fail)
  • MaxAgeSeconds: 600

AllowedHeader: * will help you the most I think, as I see Postman-Token in your request, you didn’t include that in the allowed headers you showed.

You said you got a SignatureDoesNotMatch in the original post, could you please reproduce that error and share the request/response headers&body for that instance?