2012-08-06 38 views
4

我想通過Delphi中的API訪問URL Shortener(http://goo.gl/)。 然而,唯一的結果我得到的是:HTTP/1.0 400錯誤的請求(原因:parseError)德爾福:使用Google URL Shortener與IdHTTP - 400錯誤請求

這裏是我的代碼(窗體上的一個Button1的Memo1和具有IdHTTP1IdSSLIOHandlerSocketOpenSSL1爲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密鑰(通常應該沒有一個試了幾次不錯的選擇),但如果你想用你自己去嘗試,你可以用 'https://www.googleapis.com/urlshortener/v1/url?key=<yourapikey>';

替代 actionurl

ParseError消息讓我相信longurl的編碼在發佈時可能會出錯,但我不知道要更改什麼。

我一直在模糊這一段時間,現在我確定這個錯誤在我眼前 - 我現在只是沒有看到它。 因此非常感謝任何幫助!

謝謝!

+0

我發現自己畢竟,它的偉大工程的答案,它有沒有關係後,所有的API密鑰。不幸的是,由於我是一個新用戶,並且結果不符合評論框,所以出於某些深不可測的原因,我無法將本人的答案與本網站上的新代碼一起發佈8個小時。我不知道限制是要達到什麼目的。好吧,太糟糕了。 – user1579166 2012-08-06 14:49:28

回答

2

從URL縮短API docs

每個請求您的應用程序發送給谷歌URL縮短API 需要確定您的應用程序谷歌。 有兩種方式可以識別您的應用程序:使用OAuth 2.0令牌(也可以 授權請求)和/或使用應用程序的API密鑰。

您的示例不包含用於OAuth或API密鑰身份驗證的代碼。

要使用API​​密鑰驗證,該文檔是明確的:

之後,你有一個API密鑰,應用程序可以追加查詢 參數鍵= yourAPIKey所有請求的URL。

+0

感謝您的快速回復。 API密鑰在此不是強制性的(儘管如他們所說,「強烈推薦」)。 對於少數嘗試,它通常應該沒有一個嘗試。另外,我想,上面提到的錯誤(「parseError」)並不指向apikey問題。 無論如何,我剛纔用我的鑰匙試了一下通過修改字符串「actionurl」 thuswise: https://www.googleapis.com/urlshortener/v1/url?key= 改變不了什麼,誤差保持完全相同。 有沒有其他想法? – user1579166 2012-08-06 13:11:04

+0

你可以用curl來嘗試它,並使用Fiddler或WireShark捕獲請求,然後比較它們。也許帶有TStringList參數的Post函數做得不對(基於流的帖子在當前的Indy版本中可能會更好) – mjn 2012-08-06 13:17:37

+0

在這個階段看起來有點過度,不是嗎?我也不確定這是否會有所幫助,因爲語法和方法顯然與德爾福完全不同。那麼,如果它與curl一起工作,那對我的Pascal代碼來說仍然沒有任何意義...... 你知道,我認爲在我的代碼中存在/明顯的錯字或遺漏,會立即引起別人的注意。我的意思是,只要知道你們中的任何一個人是否真的可以用相同的代碼重現解析錯誤,可能會有所幫助。 – user1579166 2012-08-06 13:23:37

4

正如您發現的那樣,TIdHTTP.Post()方法的重載版本TStrings是錯誤的使用方法。它發送一個application/x-www-form-urlencoded格式化的請求,這不適用於JSON格式的請求。你必須使用重載TStream版本的TIdHTTP.Post()方法instead`,例如:

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;