Запрос к API Amazon с delphi: получен HTTP / 1.1 403 Запрещено - PullRequest
3 голосов
/ 27 января 2012

Я не знаю, мой код правильный или неправильный.когда я пытаюсь запустить программу происходит ошибка 403 ..

unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,ssbase64, StdCtrls,secutils,OmniXMLUtils,OmniXML, xmldom,
  XMLIntf, msxmldom, XMLDoc, IdBaseComponent, IdComponent, IdTCPConnection,
  IdTCPClient, IdHTTP,IdURI;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    XMLDocument1: TXMLDocument;
    IdHTTP1: TIdHTTP;
    Memo2: TMemo;
    Memo3: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
implementation
{$R *.dfm}
function MyEncodeUrl(source:string):string;
 var i:integer;
 begin
   result := '';
   for i := 1 to length(source) do
       if not (source[i] in ['A'..'Z','a'..'z','0','1'..'9','-','_','~','.']) then result := result + '%'+inttohex(ord(source[i]),2) else result := result + source[i];
 end;

procedure TForm1.Button1Click(Sender: TObject);
var
  uhost,uri,public_key, private_key,signature,timestamp,string_to_sign : string;
  request : String;
begin
uhost  := 'ecs.amazonaws.com';
uri   := 'onca/xml';
public_key    := '1ETPTJHQ37P671HNXXX';
private_key     := 'j4JtMHQwL6wR39fy2CJgNfHibLjK9GsC5Z6XXXX';
timestamp     := MyEncodeUrl(XMLDateTimeToStr(now));
string_to_sign := 'AWSAccessKeyId=1ETPTJHQ37P671HN9282';
string_to_sign := string_to_sign+ '&AssociateTag=moc-20&ItemPage=1&Keywords=kitchen%20aid&Operation=ItemSearch&ResponseGroup=Large&SearchIndex=Kitchen&';
string_to_sign := string_to_sign+'service=AWSECommerceService&Timestamp='+timestamp;
string_to_sign := string_to_sign+'&Version=2009-03-31';

Memo1.Clear;
Memo1.Lines.Append('GET');
Memo1.Lines.Append('ecs.amazonaws.com');
Memo1.Lines.Append('/onca/xml');
Memo1.Lines.Append(string_to_sign);

signature := StrToMime64(HMACString(haSHA256, private_key, 32, Memo1.Text));
request := 'http://ecs.amazonaws.com/onca/xml?AWSAccessKeyId=1ETPTJHQ37P671HN9282';
request := request+ '&AssociateTag=moc-20&ItemPage=1&Keywords=kitchen%20aid&Operation=ItemSearch&ResponseGroup=Large&SearchIndex=Kitchen&';
request := request+'service=AWSECommerceService&Timestamp='+timestamp;
request := request+'&Version=2009-03-31';
request := request+'&Signature='+signature;

Memo1.Text := IdHTTP1.Get(request);
end;
end.

Может ли любое тело отслеживать мою ошибку ??

1 Ответ

6 голосов
/ 27 января 2012

Amazon фактически отправляет обратно XML-документ, в котором точно описывается причина ошибки 403. Самый простой способ увидеть сообщение - использовать Fiddler и настроить Indy HTTP на использование 127.0.0.1 в качестве прокси. Таким образом весь ваш трафик проходит через Fiddler, и вы увидите как то, что отправили, так и то, что вернул Amazon.

Когда я реализовал свой REST API для работы со службой Amazon S3, у меня возникли проблемы с определением «канонических заголовков», которые необходимо подписать. К счастью, Amazon API отправляет вам обратно текст, который они подписывают, чтобы проверить вашу подпись, чтобы вы могли сравнить этот побайтный байт и выяснить, делаете ли вы это неправильно. Неспособность подготовить эти «канонические заголовки» точно так же, как они готовят эти заголовки, очевидно, приведет к 403. Например, разделитель строк, используемый Amazon, - LINEFEED (#10). Поскольку вы помещаете свои заголовки в TMemo, вы получите разделитель CRLF в стиле Windows. Одного этого достаточно, чтобы ваш код потерпел неудачу.

Другая проблема, с которой у меня были проблемы, - отправка дополнительных заголовков с моими запросами Indy. Я следил за примерами онлайн-API, смотрел на то, что я должен отправить, и на что Amazon должен ответить. Fiddler был единственным способом на самом деле проверить и посмотреть, что я посылаю, в отличие от того, что я думал, что я отправлял. Например, я по ошибке использовал TIdHttp.Request.RawHeaders для записи своих пользовательских заголовков, но эти заголовки сбрасываются при подготовке запроса. Я должен был написать свои заголовки в TIdHttp.Request.CustomHeaders - но без помощи Фиддлера я бы не знал, что я на самом деле не отправляю свои заголовки. Мой код выглядел просто отлично.

...