【问题标题】:Delphi: Using Google URL Shortener with IdHTTP - 400 Bad RequestDelphi:使用带有 IdHTTP 的 Google URL Shortener - 400 错误请求
【发布时间】:2012-08-06 12:18:58
【问题描述】:

我正在尝试从 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 在发布时的编码可能有问题,但我不知道要更改什么。

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

谢谢!

【问题讨论】:

  • 毕竟我自己找到了答案,它很好用,毕竟它与 api 密钥无关。不幸的是,由于一些深不可测的原因,我被阻止在这个网站上发布我自己的新代码的答案再过 8 个小时,因为我是新用户,结果不适合评论框。我不知道这个限制意味着什么。好吧,太糟糕了。

标签: delphi api openssl idhttp


【解决方案1】:

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

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; 

【讨论】:

    【解决方案2】:

    来自 URL 缩短器API docs

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

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

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

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

    【讨论】:

    • 感谢您的快速回复。 API 密钥在这里不是强制性的(尽管正如他们所说,“强烈推荐”)。对于少数尝试,它通常应该在没有一次的情况下通过。另外,我认为我上面提到的错误(“parseError”)并不指向 apikey 问题。无论如何,我刚刚通过修改字符串“actionurl”来尝试使用我的密钥:googleapis.com/urlshortener/v1/url?key=<myapikey> 没有任何改变,错误保持完全相同。还有其他想法吗?
    • 您可以尝试使用 curl 并使用 Fiddler 或 WireShark 捕获请求,然后进行比较。也许带有 TStringList 参数的 Post 函数做得不对(基于流的帖子在当前的 Indy 版本中可能会更好地工作)
    • 现阶段似乎有点矫枉过正,不是吗?我也不确定这实际上是否有益,因为语法和方法显然与 Delphi 完全不同。那么,如果它与 curl 一起工作,那对我的 Pascal 代码仍然没有任何意义……你看,我认为我的代码中存在/只是一个明显的错字或遗漏,会立即引起人们的注意。我的意思是,只要知道你们中的任何人是否可以用相同的代码实际重现解析错误可能会有所帮助。
    • >>带有 TStringList 参数的 Post 函数运行不正确(基于流的 post 可以更好地工作
    • 毕竟我自己找到了答案,它很好用,毕竟它与 api 密钥无关。不幸的是,由于一些深不可测的原因,我被阻止在这个网站上发布我自己的新代码的答案再过 8 个小时,因为我是一个新用户。我不知道这个限制意味着什么。好吧,太糟糕了。
    猜你喜欢
    • 1970-01-01
    • 2012-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-08
    • 2016-02-26
    • 1970-01-01
    • 2013-11-29
    相关资源
    最近更新 更多