ROHttpApiDispatcher in DA/Delphi for REST

Hi,

I’m attempting to write a DA server in Delphi and want to add REST capabilities in addition to using the binary connection for remote datasets. I would like to expose REST methods for tables within the Schema.

I am using ROHttpApiDispatcher, and adding methods which show up as part of the /api/ path. I can define a method in my DataService, such as GetFoo() with an http api HttpApiPath attribute of /foo/{AId}. I can call the API from Postman using localhost:8099/api/foo/1. The value of 1 is then passed to the GetFoo() method as a parameter. This is working well.

Is there a better way of configuring this, or some other component that would provide REST methods generated directly from the Schema? I have looked at the ODataSchemaDispatcher, but it is limited to odata v1 and that may be an issue. I want to make sure that I’m not overlooking something or some component that would generate basic REST methods directly from the Schema.

Follow-up questions:
I am getting run time errors and I have not determined how to properly set things up when using QueryParams as part of the request:

I.e., I would like to make a request via Postman “localhost:8099/api/foo/1?option1=value1&option2=value2”

option1=value1 and option2=value2 are optional and neither, one, or both could be passed.

When I attempt this, I get 500 error with invalid path back: Invalid Path

I can see that in uROHttpApiUtils.pas, the ParseParameters() procedure is called, and the aRequest.QueryString is examined. The line:

lent := aRoute.Operation.ItemByName(lname);   // lname = "option1"

is returning nil, which causes the 500 error.

How do I configure the Foo() method so the aRoute.Operation value would be found and the 500 error is not generated? Once I get past that, how do I access the TROJsonMessage with the params object within the DataService Foo method?

Thanks,
Leo

Hi,

Have you read the HttpAPI in details article?

Have you added HttpApiQueryParameter=1 attribute for optional parameters?

This declaration works as expected for me:

    [ROServiceMethod]
    [ROCustom('HttpApiPath', '/foo/{AId}')]
    [ROCustom('HttpApiMethod','GET')]
    procedure NewMethod(
      [ROStreamAs(emAnsi)] const AId: string;
      [ROCustom('HttpApiQueryParameter', '1')]
      [ROStreamAs(emAnsi)] const Option1: string;
      [ROCustom('HttpApiQueryParameter', '1')] 
      [ROStreamAs(emAnsi)] const Option2: string);

Thanks for the info. I had been using the RODL and converted to code-first. The ROCustom tags did not get generated so I must have had them defined incorrectly. Adding them in the code-first server worked as expected.

As a follow-up question, if I pass a parameter that is not defined as a HttpApiResult, is there a way to change the exception that is returned?

-Leo

Hi,

You can raise EROHttpApiException like

procedure TSampleService.DeleteFromCache(key: String);
begin
  if not _dataCache.ContainsKey(key) then raise EROHttpApiException.Create(HTTP_404_code, HTTP_404_status);
  _dataCache.Remove(key);
end;