Adding HttpAPI to a Server (Delphi)
This topic will run you through the steps of adding HttpAPI support to a Remoting SDK server. If you don't have a server project yet, create a new CodeFirst Remoting SDK application using the corresponding template.
Then drop TROHttpApiDispatcher to near ROServer component and link it with ROServer via Object Inspector or manually like
procedure TServerForm.FormCreate(Sender: TObject);
begin
ROHttpApiDispatcher1.Server := ROServer; //<<<<
ROServer.Active := true;
end;
You can now run the server and go to http://localhost:8099/api
and have a look. The server will expose its meta-information there as JSON, e.g.:
{
"swagger":"2.0",
"info":{
"title":"NewLibrary",
"version":"1.0.0"
},
"basePath":"\/api",
"consumes":[
"application\/json"
],
"produces":[
"application\/json"
],
"paths":{
}
}
As an exersise modify the dispatcher's properties to expose base hostname, custom server name and version.
Now let's expose some server methods to play with. Add a new service to the server defined as such:
unit SampleService_Impl;
{$I RemObjects.inc}
interface
uses
System.SysUtils, System.Classes, System.TypInfo, System.Generics.Collections,
uROXMLIntf, uROClientIntf, uROClasses, uROTypes, uROServer, uROServerIntf, uROSessions,
uRORemoteDataModule, uRORTTIAttributes, uRORTTIServerSupport, uROArray;
const
__ServiceName ='SampleService';
type
[ROService(__ServiceName)]
TSampleService = class(TRORemoteDataModule)
public
[ROHttpAPIMethod('convert/{value}')]
function ConvertToString(value: Integer): String;
[ROHttpAPIMethod('calculate', 'GET')]
function Calculate([ROHttpAPIQueryParameter] a: Integer;
[ROHttpAPIQueryParameter] b: Integer): TROArray<Integer>;
[ROHttpAPIMethod('cache/{key}', 'POST', 201)]
procedure AddToCache(key: String;
[ROHttpAPIQueryParameter] value: String);
[ROHttpAPIMethod('cache/{key}', 'GET')]
function ReadFromCache(key: String): String;
[ROHttpAPIMethod('cache/{key}', 'PUT')]
procedure UpdateCache(key: String;
[ROHttpAPIQueryParameter] value: String);
[ROHttpAPIMethod('cache/{key}', 'DELETE')]
procedure DeleteFromCache(key: String);
end;
implementation
uses
uROHttpApiUtils, uROHTTPTools;
{$R *.dfm}
var
_dataCache: TDictionary<String, String>;
const
HTTP_409_code = 409;
HTTP_409_status = 'Conflict';
{ TNewService }
procedure TSampleService.AddToCache(key, value: String);
begin
if (_dataCache.ContainsKey(key)) then raise EROHttpApiException.Create(HTTP_409_code, HTTP_409_status);
_dataCache.Add(key, value);
end;
function TSampleService.Calculate(a, b: Integer): TROArray<Integer>;
begin
Result := TROArray<Integer>.Create;
Result.Add(a * b);
// This code line will result in the DivideByZero exception
// if the b parameter value is not provided or its value is 0
// Client will receive a generic 500 Internal Server Error response code
Result.Add(Round(a / b));
Result.Add(a + b);
Result.Add(a - b);
end;
function TSampleService.ConvertToString(value: Integer): String;
begin
Result := 'The value is ' + IntToStr(value);
end;
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;
function TSampleService.ReadFromCache(key: String): String;
begin
if not _dataCache.ContainsKey(key) then raise EROHttpApiException.Create(HTTP_404_code, HTTP_404_status);
result := _dataCache[key];
end;
procedure TSampleService.UpdateCache(key, value: String);
begin
if not _dataCache.ContainsKey(key) then raise EROHttpApiException.Create(HTTP_404_code, HTTP_404_status);
_dataCache[key] := value;
end;
initialization
RegisterCodeFirstService(TSampleService);
_dataCache:= TDictionary<String, String>.Create;
finalization
_dataCache.Free;
end.
Note how several service methods are defined on the same HTTP path. Also take a look how custom error codes are returned to the client.
Restart the server and go to http://localhost:8099/api
again. If everything was done correct you'll see much longer service description JSON than in the first time.
You can open the online Swagger Editor and copy-paste the API description JSON from http://localhost:8099/api
. This tool not only allows to generate the client-side code to access the server, it also allows to try out the server methods:
Play with different methods and key values to see how the *cache method will return different results and Http result codes.