Jump to content
David Schwartz

Curious TRESTRequest behavior

Recommended Posts

I've got a datamodule with these components on it:

 

  • TOAuth2Authenticator
  • TRESTClient
  • TRESTRequest
  • TRESTResponse

 

I'm using them to make a request of a service, and it works fine. Here's what the code looks like:

  RESTClient.BaseURL := BASE_URL+'list';  // second endpoint is 'api'
  RESTRequest.Params.Clear;
  RESTRequest.AddParameter( 'language', aLanguage );
  RESTRequest.Execute;
  Result := RESTResponse.Content;

 

Then I change the endpoint and clear params and make another request, and it blows up. Here's a bit of test code:

 

      RESTClient.BaseURL := BASE_URL+'api';
      try
        RESTRequest.AddParameter( 'abcdef', 'kljahsldfkjashdf' );
      except
        on e:Exception do
          Logger.Debug('--> *** blew up assigning Parameter: '+e.Message);
      end;

 

Here's the response in the Logger:

 

*** blew up assigning Parameter: Access violation at address 00DED977 in module 'MyWebService.exe'. Read of address FF000240

I have tried everything I can think of, but it just isn't working.  (I also tried RESTRequest.Params.AddItem(...) but it does the same thing.)

 

I can call the first API as many times as I want, and it works perfectly.

 

I can go back and forth -- the first one always works, the second one always fails at the same point.

 

It looks to me like there may be a data overrun, but ... why?

 

Any ideas or suggestions?

 

Edited by David Schwartz

Share this post


Link to post

Can you make a minimal example to reproduce?

 

Oh, and:

9 minutes ago, David Schwartz said:

Then I change the endpoint and clear params and make another request,

In contrast to your statement you don't clear the params in the shown code.

 

BTW, you should keep the BaseURL as is and put the endpoint in RESTRequest.Resource instead.

Edited by Uwe Raabe

Share this post


Link to post

Right now I'm simply asking if this looks familiar to anybody. I've been messing with it for a week now and this is as much clarity as I can get.

 

I *AM* clearing the params in the first endpoint, but in the second one is where it blows up. ANY attempt to alter Params in the second case blows up.

 

It's running in the service so it's hard to track down specifics. The exact same code unit is compiled into another project that all runs locally and it works fine -- I can call both APIs and they work perfectly.

 

Go figure.

 

I'll change the BaseURL setting as you suggest. I forgot about that... been too focused on this main issue.

 

 

Edited by David Schwartz

Share this post


Link to post
18 minutes ago, David Schwartz said:

It's running in the service so it's hard to track down specifics. The exact same code unit is compiled into another project that all runs locally and it works fine

In that case the problem seems to be outside of the code in question. My guess is that either RESTRequest is destroyed in between or some memory is overwritten, but I doubt that the component itself is responsible for that.

 

That's why I asked for a reproducible test case. Usually when one cannot create a reproducible test case, the problematic code part lies outside of the tested one.

Share this post


Link to post

It CAN'T be destroyed! As I said, I can flip between each API request -- the first one always works, the second one always blows up on any attempt to modify Params.

 

These four objects are on the DataManager "form".

 

It's the SAME OBJECT in BOTH cases! 

 

And it did the same thing if I duplicated all of the REST objects and ran them each separately, one set for each API. 

 

There's very little logic going on outside of what I showed. A button click goes to each of the methods and that's pretty much all that's done -- Set the API endpoint, clear Params, add new Params, call Execute and wait for the result.

 

Both are POST requests, both are using the same auth details, ... there just aren't that many variables to test.

 

I guess I'll create three of these four REST objects dynamically (using the auth object as it is) and see what happens.

 

If that doesn't work, I'll make another unit and put the second call there and see if that makes any difference.

 

 

Edited by David Schwartz

Share this post


Link to post

Your code in the first post is very minimalist, so, I ask?

Is there any possibility that, in your parameter change, there is a loss of some property that connects the components to each other? (i mean, some property is getting blank = nil)

Share this post


Link to post

I don't know. These are standard Delphi components, and the Params is a TCollection. I just call Clear to rest them and then add new ones that are arguments for the POST request.

 

As I said, I can go back and forth, and the first API works -- once, twice, five times, however many in a row you want, using different arguments -- and then go to the second API and it fails at the same place every time -- once, twice, ... every time. Back to the first API and it works fine.

 

It blows up simply CLEARING the Params -- I cannot SET any of them. Even if I comment out the Params.Clear it blows up on the first AddParameter / Params.AddItem call it encounters.

 

It's a real head-scratcher.

 

It's ONLY happening inside of the service. But I have no way to debug it ... do I? Can delphi debug it running locally?

 

I was also thinking there could be some threading involved and this could be due to a race condition, but it would all be implicit as I don't do any explicit threading.

 

 

 

Edited by David Schwartz

Share this post


Link to post

have you try use "RESTClient1.Params.ClearAndResetID" ?

Quote

procedure TCollection.ClearAndResetID;  // System.Classes.pas, line 6341
begin
  Clear;
  FNextID := 0;
end;

 

Quote

function TRESTRequestParameterList.AddItem((...) REST.Client.pas, line 2540....  try add or re-use old param item...

 

    i := IndexOf(AName);
    if i = -1 then
      Result := AddItem
    else
      Result := Items;
 

 

Edited by programmerdelphi2k

Share this post


Link to post

O K ... mystery solved ...

 

It looked like a data overrun problem because ... it was. I failed to create an instance of the DataModule I was using, and somehow the first part worked, but the later part looked like it had been overwritten ... which it had.

 

In my experience, when objects haven't been created, they blow up right away. I'll have to remember this -- strange memory overwrite symptoms can be because the object wasn't created!

 

Edited by David Schwartz
  • Like 1

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

×