Automattic / knox

S3 Lib
MIT License
1.74k stars 285 forks source link

PUT works inconsistent. #278

Open delgermurun opened 9 years ago

delgermurun commented 9 years ago

I created bucket in US Standart region. I'm uploading file via stream.

So sometimes it works, sometimes not. I tried to set region to us-west-2 and 'us-east-1`, but still same. Works inconsistent.

Error message is:

<Error><Code>SignatureDoesNotMatch</Code>
<Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message><AWSAccessKeyId>AKIAJOX5SZFWUSX6AHRA</AWSAccessKeyId><StringToSign>

status code is 403

lbeschastny commented 8 years ago

I encountered the same issue just now and found what was causing it in my project.

When knox generates signed AWS uri it relies on require('querystring').stringify here, but some third-party modules may monkey-patch it. For example, googlemapsutil overwrites require('querystring').escape method with identity function. Because of it, require('querystring').stringify leaves all '+' characters unencoded instead of encoding them with '%2B' string.

But when AWS receives your request, it decodes all '+' characters to white spaces (which is also an incorrect behavior in my opinion).

So, if generated signature contain any number of '+' characters then you'll receive AWS API error, telling you that SignatureDoesNotMatch. If you'll look closely at returned XML you'll see that SignatureProvided field contains your signature with all '+' characters replaced by white spaces.

You could fix it by restoring require('querystring').escape function:

require('querystring').escape = function (str) {
  return encodeURIComponent(str);
}

or by replacing all '+' characters in a generated uri with '%2B' string yourself.