SignatureDoesNotMatch error when Content-type is 'text/*' using TAmazonStorageService.UploadObject
Asked Answered
U

2

6

Using the following Delphi XE2 (update 4) code:

var
  ConInfo: TAmazonConnectionInfo;
  RespInfo: TCloudResponseInfo;
  Service: TAmazonStorageService;
  Content: TBytes;
  Headers: TStringList;
begin
  ConInfo:=TAmazonConnectionInfo.Create(self);
  ConInfo.AccountName:='YOUR ACCOUNT NAME';
  ConInfo.AccountKey:='YOUR ACCOUNT KEY';
  ConInfo.Protocol:='http';

  Service:=TAmazonStorageService.Create(ConInfo);
  RespInfo:=TCloudResponseInfo.Create;

  SetLength(Content, 128);
  FillMemory(@Content[0], 128, Byte('x'));

  Headers:=TStringList.Create;
  Headers.Values['Content-type']:='text/plain';
  if not Service.UploadObject('YOUR BUCKET', 'test.txt', Content, TRUE, nil, Headers, amzbaPrivate, RespInfo) then
    ShowMessage('Failed:' + RespInfo.StatusMessage);

I always get an error on the call to UploadObject:

Failed:HTTP/1.1 403 Forbidden - The request signature we calculated does not match the signature you provided. Check your key and signing method. (SignatureDoesNotMatch)

This only happens when the Content-type is set to 'text/plain', 'text/html', or text anything. Using exactly the same code, if you just change the content-type to any other content-type, e.g. 'video/3gpp', then it works as expected and without error. The actual content of the object being uploaded isn't relevant and has no bearing on getting the error or not.

I've traced through the Indy code in Delphi, but I'm stumped as to why the text content type always gives this error.

Any ideas?

Ullyot answered 26/4, 2012 at 8:19 Comment(0)
U
4

If you append "; charset=ISO-8859-1" to the Content-Type string, then it works:

Headers.Values['Content-type']:='text/plain; charset=ISO-8859-1';

Stepping through the code I see the Content-Type is being changed in TIdEntityHeaderInfo.SetHeaders (IdHTTPHeaderInfo.pas) which is called from TIdHTTPProtocol.BuildAndSendRequest (IdHTTP.pas).

Ultimately, it looks like the problem is that TIdEntityHeaderInfo.SetContentType (IdHTTPHeaderInfo.pas) is appending a character set to the content type if it is 'text' and it doesn't already have one. It shouldn't be changing the content type in these situations because the content type is part of the string to be signed, so changing it after the signing makes the signature invalid.

Ullyot answered 26/4, 2012 at 14:33 Comment(1)
Glad you were able to fix it yourself. I came across this exact same problem when trying to updload text/html. At the time I resorted to just "html" - but then Internet Explorer had problems viewing the files. Thanks for sharing!!!!!Ursuline
M
0

I had the very same problem. I also used application/octet-stream as content type, but still had some trouble. Later on, I discovered that bucket names have to be in lowercase (In US Standard Region, Amazon allows to define buckets with Uppercase or mixed case names; however, those buckets are not accessible through the HTTP API (including TAmazonStorageService). Instead of a not found message, I still got the 403 error (unauthenticated user). However, one I changed the name to all lowercase, it worked fine. Hope it helps

Metamorphism answered 3/11, 2014 at 20:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.