Jump to content
ToddFrankson

TRestRequest and IOS...

Recommended Posts

Are there any Issues with TRestRequest and IOS?  The following Code runs on Android, Windows 32bit & 64bit, and MacOS fine, but on IOS I get nothing in the TRestResponse contents:

 

procedure TForm1.Button1Click(Sender: TObject);

begin   
   Memo1.lines.clear;
   TTask.run(Procedure

    Begin
      RestRequest1.execute; 

   End).Start;    

end;

 

And the RestRequest Handler-

procedure TForm1.RESTRequest1AfterExecute(Sender: TCustomRESTRequest);
begin
  Try
     Begin
       Accesstoken:=restresponse1.JSONValue.GetValue<string>('access_token');
       Memo1.lines.add(Accesstoken);
       TDialogservice.showmessage('Access Token: ' + AccessToken);
     End;
  Except on E:Exception do
    TDialogservice.showmessage(E.message);

  End;
end;

 

Everytime I hit   Accesstoken:=restresponse1.JSONValue.GetValue<string>('access_token'); the restresponse content is ''.  But only on IOS.

 

Anyone have ideas where to look?  Maybe a property I need to set?  I can post the form code if needed.

Share this post


Link to post
14 minutes ago, Olli73 said:

Instead of creating your own thread/task, you could/should use "RestRequest1.ExecuteAsync(...)".

I tried that too,  It works on all platforms except IOS.  Thats what lead me to try this. It's like the RESTRequest1AfterExecute comes back before the request is completed

Edited by ToddFrankson

Share this post


Link to post

In case of ExecuteAsync, have you used the ACompletionHandler Parameter instead of the Afterexecute event and also set the ASynchronized Parameter to true?

  • Like 1

Share this post


Link to post

Same issue.  That was where this started.  

 

procedure TForm1.Button1Click(Sender: TObject);

begin
   RESTRequest1.AcceptEncoding := 'gzip, deflate, br';
   Memo1.lines.clear;
    RestRequest1.ExecuteAsync(MyHandler,true,true,nil);  

end;

 

procedure TForm1.myHandler;
begin
  Try
     Accesstoken:=restresponse1.JSONValue.GetValue<string>('access_token');
     Memo1.lines.add(Accesstoken);
     showmessage('Access Token: ' + AccessToken);
  Except on E:Exception do
    showmessage(E.message);

  End;

 

When I tap button1 to fire RestRequest1.ExecuteAsync(MyHandler,true,true,nil);  almost immediately I go right to Accesstoken:=restresponse1.JSONValue.GetValue<string>('access_token'); 

Then it hits the Exception, where Accesstoken is '', and never shows the error message.

Share this post


Link to post
On 11/28/2024 at 10:31 PM, ToddFrankson said:

     Accesstoken:=restresponse1.JSONValue.GetValue<string>('access_token');

Is at this place something filled in "restResponse1.Content"?

Is the value later (after the Handler) filled?

 

And what is the StatusCode of the response?

Edited by Olli73

Share this post


Link to post
18 hours ago, Olli73 said:

Is at this place something filled in "restResponse1.Content"?

Is the value later (after the Handler) filled?

 

And what is the StatusCode of the response?

1-It should be, bu tit is not. Content=''.- Works on all platforms but IOS-I used the REST Debugger to generate the objects.

2-On all other platforms it is, but not on IOS

3- the response code is 0- i have been digging into the HTTPClient in the rest Request.  It seems on IOS it's doing a handoff to the OS with a callback. 

 

Line 517-522 of System.Net.HTTPClient.mac is where it fails on IOS Emulator (So I can step through the code)

 

LResponse.FDone := False;
  FDataTasks.AddTask(LRequest.FDataTask, LResponse);
  try
    LRequest.FDataTask.resume;
    while not LResponse.FDone do
      InternalWaitMessage(0.01);  --> This procedure  

 

Located at 330-338:

procedure InternalWaitMessage(AInterval: Single);
var
  TimeoutDate: NSDate;
begin
  TimeoutDate := TNSDate.Wrap(TNSDate.OCClass.dateWithTimeIntervalSinceNow(AInterval));
  TNSRunLoop.Wrap(TNSRunLoop.OCClass.currentRunLoop).runMode(NSDefaultRunLoopMode, TimeoutDate);
  if TThread.CurrentThread.ThreadID <> MainThreadID then
    Sleep(Trunc(AInterval * 1000));
end;

 

Lines 1309-on in System.Net.HTTPCLient is where the LResponse.Cancelled is set to true:

 if LRequest.FCancelled then----->Cancelled is false;
        Exit;
      LExecResult := DoExecuteRequest(LRequest, LResponse, AContentStream);
      if LRequest.FCancelled then--------------Cancelled is true
        Exit;
      case LExecResult of
        TExecutionResult.Success: ------>Status is success, but the exit above spits us out
          begin
            if not SameText(LRequest.FMethodString, sHTTPMethodHead) and
               (LResponse.FStream <> nil) then
              LResponse.DoReadData(LResponse.FStream);
            if LRequest.FCancelled then
              Exit;
            Status := LResponse.GetStatusCode;------------Status code is 200 but Cancelled set to true means we've exited
            case Status of
              200:
                begin
                  Break;
                end;
              401:

 

......

 

 

And today I get an SSL error at line 529 of System.Net.HTTPClient.mac:

 

 else if LResponse.FError <> nil then------------------------->
      raise ENetHTTPClientException.CreateResFmt(@SNetHttpClientErrorAccessing,
        [LResponse.FError.code, LRequest.FURL.ToString, NSStrToStr(LResponse.FError.localizedDescription)])

 

End;

Edited by ToddFrankson

Share this post


Link to post

Got it.  It seems IOS had to have a slightly different URL............  The API provider needs better documentation.

 

 

All is good in the universe again.  Thanks for helping me brainstorm 

Share this post


Link to post

And just like that, Response code of 0 with ZERO code changes.  Even the Postman App on IOS fails following the instructions from the website.

 

There's something fishy with REST and IOS

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×