4

我正在尝试从 Delphi 中通过其 API访问 URL Shortener ( http://goo.gl/ )。但是,我得到的唯一结果是:HTTP/1.0 400 Bad Request (reason: parseError)

这是我的代码(在带有Button1Memo1IdHTTP1的表单上,其中IdSSLIOHandlerSocketOpenSSL1作为其 IOHandler。我从http://indy.fulgan.com/SSL/获得了必要的 32 位 OpenSSL DLL ,并将它们放在 . exe的目录):

procedure TFrmMain.Button1Click(Sender: TObject);
    var html, actionurl: String;
    makeshort: TStringList;
begin
try
 makeshort := TStringList.Create;

 actionurl := 'https://www.googleapis.com/urlshortener/v1/url';
 makeshort.Add('{"longUrl": "http://slashdot.org/stories"}');

 IdHttp1.Request.ContentType := 'application/json';
 //IdHTTP1.Request.ContentEncoding := 'UTF-8'; //Using this gives error 415

 html := IdHTTP1.Post(actionurl, makeshort);
 memo1.lines.add(idHTTP1.response.ResponseText);

     except on e: EIdHTTPProtocolException do
        begin
            memo1.lines.add(idHTTP1.response.ResponseText);
            memo1.lines.add(e.ErrorMessage);
        end;
    end;

 memo1.Lines.add(html);
 makeshort.Free;
end;

更新:我在这个例子中没有使用我的 API 密钥(通常应该可以在没有尝试几次的情况下正常工作),但如果你想用自己的方式尝试,你可以将actionurl字符串 替换为'https://www.googleapis.com/urlshortener/v1/url?key=<yourapikey>';

ParseError 消息使我相信 longurl 在发布时的编码可能有问题,但我不知道要更改什么。

我已经为此困惑了很长一段时间,我确信这个错误就在我眼前——我只是现在没有看到它。因此,非常感谢任何帮助!

谢谢!

4

2 回答 2

4

正如您所发现的,TStrings该方法的重载版本TIdHTTP.Post()是错误的使用方法。它发送一个application/x-www-form-urlencoded格式化的请求,这不适合 JSON 格式的请求。您必须改用该方法的TStream重载版本TIdHTTP.Post(),例如:

procedure TFrmMain.Button1Click(Sender: TObject); 
var
  html, actionurl: String; 
  makeshort: TMemoryStream; 
begin 
  try
    makeshort := TMemoryStream.Create; 
    try 
      actionurl := 'https://www.googleapis.com/urlshortener/v1/url'; 
      WriteStringToStream(makeshort, '{"longUrl": "http://slashdot.org/stories"}', IndyUTF8Encoding); 
      makeshort.Position := 0;

      IdHTTP1.Request.ContentType := 'application/json'; 
      IdHTTP1.Request.Charset := 'utf-8';

      html := IdHTTP1.Post(actionurl, makeshort); 
    finally
      makeshort.Free; 
    end;

    Memo1.Lines.Add(IdHTTP1.Response.ResponseText); 
    Memo1.Lines.Add(html); 
  except
    on e: Exception do 
    begin 
      Memo1.Lines.Add(e.Message); 
      if e is EIdHTTPProtocolException then
        Memo1.lines.Add(EIdHTTPProtocolException(e).ErrorMessage); 
    end; 
  end; 
end; 
于 2012-08-06T16:53:07.397 回答
2

从 URL 缩短API 文档

您的应用程序向 Google URL Shortener API 发送的每个请求都需要向 Google 识别您的应用程序。有两种方法可以识别您的应用程序:使用 OAuth 2.0 令牌(也授权请求)和/或使用应用程序的 API 密钥。

您的示例不包含 OAuth 或 API 密钥身份验证的代码。

要使用 API 密钥进行身份验证,文档很清楚:

获得 API 密钥后,您的应用程序可以将查询参数 key=yourAPIKey 附加到所有请求 URL。

于 2012-08-06T12:40:40.133 回答