Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: TIdHTTP invalid pointer operation when posting JSON to Firebase (FCM)



Permlink Replies: 2 - Last Post: Oct 16, 2017 6:53 AM Last Post By: Peter Gore
Peter Gore

Posts: 12
Registered: 9/29/06
TIdHTTP invalid pointer operation when posting JSON to Firebase (FCM)
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 13, 2017 4:14 AM
I'm developing a VCL backend application to post a JSON push notification to Android phones using Firebase Cloud Messaging, however, I always get an "Invalid pointer operation" on IdHTTP1.Post... if I include the {"data":..."} portion. Sending just {"to":...} JSON does not cause the exception. The push notification is delivered to the phone in all instances.

The required JSON is:

HTTP POST request

https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA

{ "data": {
"score": "5x1",
"time": "15:10"
},
"to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
}

Can anyone please help me solve the exception?

procedure TForm1.PushNotification( Recipient, Token, Msg : string );
var
         json : TJSONObject;
     jsondata : TJSONObject;
         data : TStringStream;
  respContent : TStringStream;
begin
  try
    JSON := TJSONObject.Create();
    JSONData := TJSONObject.Create();
    respContent := TStringStream.Create();
    try
      IdHTTP1.ReadTimeout := 30000;
      IdHTTP1.Request.ContentType := 'application/json';
      IdHTTP1.Request.CustomHeaders.Clear;
      IdHTTP1.Request.CustomHeaders.AddValue('Authorization','key=' + ServerKey);
      JSONData.AddPair('title',Msg);
      JSON.AddPair('data',JSONData);
      JSON.AddPair('to',Token);
      data := TStringStream.Create(JSON.ToString);
      Memo1.Lines.Add(JSON.ToString);
      data.Position := 0;
      Memo1.Lines.Add('Sending push notification to ' + Recipient + '...');
      IdHTTP1.Post('https://fcm.googleapis.com/fcm/send',data,respContent);
      respContent.Position := 0;
      Memo1.Lines.Add(respContent.DataString);
      Memo1.Lines.Add(Format('Result code = %d',[IdHTTP1.ResponseCode]));
    finally
      respContent.Free;
      JSONData.Free;
      data.Free;
      JSON.Free;
    end;
  except on E: Exception do
      Memo1.Lines.Add(E.Message);
  end;
end;
Remy Lebeau (Te...


Posts: 9,447
Registered: 12/23/01
Re: TIdHTTP invalid pointer operation when posting JSON to Firebase (FCM) [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 13, 2017 10:57 AM   in response to: Peter Gore in response to: Peter Gore
Peter Gore wrote:

however, I always get an "Invalid pointer operation" on
IdHTTP1.Post... if I include the {"data":..."} portion. Sending just
{"to":...} JSON does not cause the exception.

You are freeing a TJSONObject that you have no right to free.

When you call JSON.AddPair('data', JSONData), JSON takes ownership of
JSONData, and will free it when JSON is freed.

Unlike a TComponent, a TJSONValue does not remove itself from its owner
when destroyed. So, when you call JSONData.Free, you are destroying an
object that JSON still owns, and then the code crashes when JSON tries
to free JSONData a second time.

You have two choices:

1. set JSONData.Owned to False after calling AddPair('data'). JSONData
will still be in JSON's list of values, but JSON will not try to free
it anymore. This does mean you need to free JSON before JSONData,
instead of the other way around like you currently have, eg.

procedure TForm1.PushNotification( Recipient, Token, Msg : string );
var
  json : TJSONObject;
  jsondata : TJSONObject;
  data : TStringStream;
  reqContent, respContent : string;
begin
  try
    JSONData := TJSONObject.Create;
    try
      JSONData.AddPair('title', Msg);
 
      JSON := TJSONObject.Create;
      try
        JSON.AddPair('data', JSONData);
        JSONData.Owned := False; // <--
 
        JSON.AddPair('to', Token);
 
        reqContent := JSON.ToString;
      finally
        JSON.Free;
      end;
    finally
      JSONData.Free;
    end;
 
    Memo1.Lines.Add(reqContent);
 
    data := TStringStream.Create(reqContent, TEncoding.UTF8);
    try
      data.Position := 0;
 
      IdHTTP1.ReadTimeout := 30000;
      IdHTTP1.Request.ContentType := 'application/json';
      IdHTTP1.Request.CustomHeaders.Clear;
      IdHTTP1.Request.CustomHeaders.AddValue('Authorization','key=' +
ServerKey);
 
      Memo1.Lines.Add('Sending push notification to ' + Recipient +
'...');
      respContent :=
IdHTTP1.Post('https://fcm.googleapis.com/fcm/send', data);
    finally
      data.Free;
    end;
 
    Memo1.Lines.Add(respContent);
    Memo1.Lines.Add(Format('Result code = %d',[IdHTTP1.ResponseCode]));
  except
    on E: Exception do
      Memo1.Lines.Add(E.Message);
  end;
end;

2. don't try to free JSONData at all once AddPair() takes ownership of
it, eg:

procedure TForm1.PushNotification( Recipient, Token, Msg : string );
var
  json : TJSONObject;
  jsondata : TJSONObject;
  data : TStringStream;
  reqContent, respContent : string;
begin
  try
    JSON := TJSONObject.Create;
    try
      JSONData := TJSONObject.Create;
      try
        JSONData.AddPair('title', Msg);
 
        JSON.AddPair('data', JSONData);
        JSONData := nil; // <--
 
        JSON.AddPair('to', Token);
 
        reqContent := JSON.ToString;
      finally
        JSONData.Free;
      end;
    finally
      JSON.Free;
    end;
 
    Memo1.Lines.Add(reqContent);
 
    data := TStringStream.Create(reqContent, TEncoding.UTF8);
    try
      data.Position := 0;
 
      IdHTTP1.ReadTimeout := 30000;
      IdHTTP1.Request.ContentType := 'application/json';
      IdHTTP1.Request.CustomHeaders.Clear;
      IdHTTP1.Request.CustomHeaders.AddValue('Authorization','key=' +
ServerKey);
 
      Memo1.Lines.Add('Sending push notification to ' + Recipient +
'...');
      respContent :=
IdHTTP1.Post('https://fcm.googleapis.com/fcm/send', data);
    finally
      data.Free;
    end;
 
    Memo1.Lines.Add(respContent);
    Memo1.Lines.Add(Format('Result code = %d',[IdHTTP1.ResponseCode]));
  except
    on E: Exception do
      Memo1.Lines.Add(E.Message);
  end;
end;

--
Remy Lebeau (TeamB)

Peter Gore

Posts: 12
Registered: 9/29/06
Re: TIdHTTP invalid pointer operation when posting JSON to Firebase (FCM) [Edit]
Click to report abuse...   Click to reply to this thread Reply
  Posted: Oct 16, 2017 6:53 AM   in response to: Remy Lebeau (Te... in response to: Remy Lebeau (Te...
Thank you Remy for the detailed response :)
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02