Reputation: 1165
I am sending an HTTP Get request to Google's Map API, and I fill my StringStream with the response. However, when I try to read from the stream, I am just presented with an empty string ''.
{ Attempts to get JSON back from Google's Directions API }
function GetJSONString_OrDie(url : string) : string;
var
lHTTP: TIdHTTP;
SSL: TIdSSLIOHandlerSocketOpenSSL;
Buffer: TStringStream;
begin
{Sets up SSL}
SSL := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
{Creates an HTTP request}
lHTTP := TIdHTTP.Create(nil);
{Sets the HTTP request to use SSL}
lHTTP.IOHandler := SSL;
{Set up the buffer}
Buffer := TStringStream.Create(Result);
{Attempts to get JSON back from Google's Directions API}
lHTTP.Get(url, Buffer);
Result:= Buffer.ReadString(Buffer.Size); //An empty string is put into Result
finally
{Frees up the HTTP object}
lHTTP.Free;
{Frees up the SSL object}
SSL.Free;
end;
Why am I getting an empty string back, when I can see that the StringStream Buffer
has plenty of data (size of 32495 after the Get is called).
I've tested my call, and I am returned with valid JSON.
Upvotes: 1
Views: 2742
Reputation: 595392
First, you are using TStringStream
to receive the response data. If you are using Delphi 2009+, DO NOT do that! TStringStream
is tied to a specific encoding that has to be declared in the constructor before the stream is populated with data, and it cannot be changed dynamically. The default encoding is TEncoding.Default
, which represents the OS default encoding. If the HTTP response uses a different encoding, the data will not decode to a String
correctly.
Second, you are not seeking the stream's Position
back to 0 before calling ReadString()
. An easier way to retrieve a TStringStream
's content as a decoded String
is to use the DataString
property instead, which ignores the Position
property and returns the entire stream content as a whole:
Result := Buffer.DataString;
Third, you are doing too much manual work. TIdHTTP.Get()
has an overloaded version that returns a decoded String
. The benefit of using this method is that it uses the actual charset of the response, rather than the charset of a TStringStream
:
function GetJSONString_OrDie(const URL: string): string;
var
lHTTP: TIdHTTP;
SSL: TIdSSLIOHandlerSocketOpenSSL;
begin
{Creates an HTTP request}
lHTTP := TIdHTTP.Create(nil);
try
{Sets the HTTP request to use SSL}
lHTTP.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(lHTTP);
{Attempts to get JSON back from Google's Directions API}
Result := lHTTP.Get(URL);
finally
{Frees up the HTTP object}
lHTTP.Free;
end;
end;
Which can be simplified further if you are using an up-to-date version of Indy (see this blog post for details):
function GetJSONString_OrDie(const URL: string): string;
var
lHTTP: TIdHTTP;
begin
{Creates an HTTP request}
lHTTP := TIdHTTP.Create(nil);
try
{Attempts to get JSON back from Google's Directions API}
Result := lHTTP.Get(URL);
finally
{Frees up the HTTP object}
lHTTP.Free;
end;
end;
Upvotes: 5