The amazing RESTAdapter
What is RESTAdapter? RESTAdapter turn your REST API into a Delphi Interface. In practice you can declare an interface that represents your REST API and the RESTAdapter does all work for you. You have to declare a Delphi interface and then use RTTI attributes to describe the request:
- RESTResource: to describe URI and REST verb of resource
- Headers: a key-value pair that represents a Header of HTTP request
- MapperListOf: to specify the Object Type of the List
- Param: to specify that a method parameter is a param of HTTP Request
- Body: to specify that a method parameter is the body of HTTP Request
[Headers('User-Agent', 'RESTAdapter-Test')]
IRESTAPIService = interface(IInvokable)
['{58B9FA23-92F4-4B8E-814B-05232F32A41F}']
[RESTResource(HttpGet, '/persons')]
[MapperListOf(TPerson)]
function GetListPerson: TObjectList<TPerson>;
[RESTResource(HttpGet, '/persons/{personid}')]
function GetPersonByID([Param('personid')] APersonID: integer): TPerson;
[RESTResource(httpPOST, '/persons')]
function SavePerson([Body] ABody: TPerson): TPerson;
end;
After you have declared the interface and described the HTTP request by attributes, you have to use the TRestAdapter class to generate the real implementation of declared interface:
RESTAdapter := TRESTAdapter<IRESTAPIService>.Create;
RESTAPIService := RESTAdapter.Build('localhost', 9999);
Here is the magic! By now, you can call your HTTP endpoints without adding code:
Person := RESTAPIService.GetPersonByID(1);
The TRESTAdapter class inherits from TVirtualInterface. TVirtualInterface doesn't behave like an ordinary class, each instance has an associated reference counter to automatically free itself. In practice there isn't need to free the RESTAdapter object.
Attributes
More detailed information about the use of available attributes
RestResource
Allows you to describe the REST resource in terms of URI and REST verb (GET, POST, PUT, DELETE).
[RESTResource(HttpGet, '/persons')]
You can also specify query parameters in the URL:
[RESTResource(HttpGet, '/persons?sort=desc')]
You can decide to manipulate the URL dynamically by surrounding a parameter with brackets: {parameter}. Then put the Param attribute on the relative methods parameter specifying the match in the URL (the value surrounded with brackets):
[RESTResource(HttpGet, '/persons/{personid}')]
function GetPersonByID([Param('personid')] APersonID: integer): TPerson;
Header
Allows you to set header for all requests (by put the attribute on the interface declaration) or single method:
[Headers('User-Agent', 'RESTAdapter-Test')]
IRESTAPIService = interface(IInvokable)
['{58B9FA23-92F4-4B8E-814B-05232F32A41F}']
[Headers('Accept', 'application/json')]
[Headers('ContentType', 'application/json')]
[RESTResource(HttpGet, '/testconsumejson')]
function HeadersApplicationJSON: TJSONValue;
end;
Both Headers, interface and method, will be included in the request.
Body
Allows you to specify an object for use as an HTTP request body by putting the Body attribute.
[RESTResource(httpPOST, '/persons')]
function SavePerson([Body] ABody: TPerson): TPerson;
The object will be converted in JSON format.