I'm trying to serve a REST API service locally in a small business environment using idHTTPserver with Delphi Xe5. I pre process the file before sending it to the client, something is going wrong at this point. The memory is not released after the process its completed.
The JSON Object created is sent correctly to the client after all (AngularJS App)
What am I doing wrong?
When I receive a HTTP Client request I do this..
Procedure TMain.IdHTTPServer1CommandGet(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
Var
// Here Var Types
Json,LFilename:String;
ROOTCOMANDAS,TORDEN,DATA,MSG : TJSONObject;
Dlnew,d : TJSONArray
files:tfilestream;
Begin
LFilename := ARequestInfo.Document;
if AnsiSameText(LFilename, '/resto/orders/jsondata') then
begin
files := TFileStream.Create('htd' + LFilename, fmOpenRead + fmShareDenyWrite);
Json := ReadStringFromStream(files);
files.Free;
ROOTCOMANDAS := TJSONOBJECT.ParseJSONValue(TEncoding.ASCII.GetBytes(Json), 0) as TJSONOBJECT;
try
Data := ROOTCOMANDAS.Get('data').JSONValue as TJSONOBJECT;
d := Data.Get('d').JSONValue as TJSONArray;
dlnew := TJSONArray.Create;
for LValue in d do
if (LValue as TJSONOBJECT).GetValue('ss').Value = '0' then
dlnew.AddElement(LValue);
TORDEN := TJSONOBJECT.Create;
Msg := TJSONOBJECT.Create;
Msg.AddPair(TJSONPair.Create('t', TJSONString.Create('m5000_325')));
Msg.AddPair(TJSONPair.Create('tipo', TJSONNumber.Create(5)));
TORDEN.AddPair(TJSONPair.Create('msg', Msg));
Msg := TJSONOBJECT.Create;
Msg.AddPair(TJSONPair.Create('et', TJSONString.Create(ETAGL)));
Msg.AddPair(TJSONPair.Create('d', dlnew));
TORDEN.AddPair(TJSONPair.Create('data', Msg));
TORDEN.AddPair(TJSONPair.Create('ok', TJSONTrue.Create));
TORDEN.AddPair(TJSONPair.Create('md', TJSONNumber.Create(iFD)));
TORDEN.AddPair(TJSONPair.Create('time', TJSONString.Create(UTC)));
Json := TORDEN.ToString;
AResponseInfo.CacheControl := 'no-cache';
AResponseInfo.CustomHeaders.Values['Access-Control-Allow-Headers'] := 'Content-Type';
AResponseInfo.CustomHeaders.Values['Access-Control-Allow-methods'] := 'GET,POST,OPTIONS';
AResponseInfo.CustomHeaders.Values['Access-Control-Allow-origin'] := '*';
AResponseInfo.CharSet := 'utf-8';
AResponseInfo.Pragma := 'Public';
AResponseInfo.Server := 'Drone';
AResponseInfo.ContentText := Json;
finally
ROOTCOMANDAS.Free;
end;
exit;
end;
You are never releasing TORDEN
variable, hence the memory leak, and error you get when you do try to release it is caused by following lines:
for LValue in d do
if (LValue as TJSONOBJECT).GetValue('ss').Value = '0' then
dlnew.AddElement(LValue);
LValue
is owned by d
and will be released when d
is released, and you are adding LValue
to dlnew
that will also want to release it. You have ownership issue here because two objects want to own and release same contained object.
Try following changes to solve the issue:
for LValue in d do
if (LValue as TJSONOBJECT).GetValue('ss').Value = '0' then
begin
dlnew.AddElement(LValue);
// here you are saying that you don't want to release object when ROOTCOMANDAS is released
LValue.Owned := false;
end;
// release ROOTCOMANDAS and d along with it
ROOTCOMANDAS.Free;
// Set back owned property to true so you don't leak objects
for LVaue in dlnew do
LValue.Owned := true;
...
Json := TORDEN.ToString;
TORDEN.Free;
... remove superfluous ROOTCOMANDAS.Free; in finally part