I'm trying to access the URL Shortener ( http://goo.gl/ ) via its API from within Delphi. However, the only result I get is: HTTP/1.0 400 Bad Request (reason: parseError)
Here is my code (on a form with a Button1, Memo1 and IdHTTP1 that has IdSSLIOHandlerSocketOpenSSL1 as its IOHandler. I got the necessary 32-bit OpenSSL DLLs from http://indy.fulgan.com/SSL/ and put them in the .exe's directory):
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;
Update: I have left off my API key in this example (should usually work well without one for a few tries), but if you want to try it with your own, you can substitute the actionurl string with
'https://www.googleapis.com/urlshortener/v1/url?key=<yourapikey>';
The ParseError message leads me to believe that there might be something wrong with the encoding of the longurl when it gets posted but I wouldn't know what to change.
I've been fuzzing over this for quite a while now and I'm sure the mistake is right before my eyes - I'm just not seeing it right now. Any help is therefore greatly appreciated!
Thanks!
As you discovered, the TStrings
overloaded version of the TIdHTTP.Post()
method is the wrong method to use. It sends an application/x-www-form-urlencoded
formatted request, which is not appropriate for a JSON formatted request. You have to use the TStream
overloaded version of the TIdHTTP.Post()
method instead`, eg:
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;
From the URL shortener API docs:
Every request your application sends to the Google URL Shortener API needs to identify your application to Google. There are two ways to identify your application: using an OAuth 2.0 token (which also authorizes the request) and/or using the application's API key.
Your example does not contain code for OAuth or API key authentication.
To authenticate with an API key, the docs are clear:
After you have an API key, your application can append the query parameter key=yourAPIKey to all request URLs.
来源:https://stackoverflow.com/questions/11828153/delphi-using-google-url-shortener-with-idhttp-400-bad-request