How to create an API(WebServer) in Delphi
An API is a very powerful feature when you want your app working on a Tablet, Smartphone, Desktop or a Website. You can integrate all your platforms and have your app working on multiple platforms calling the same database.
When it comes to web server, Delphi is a superpower. I built an API with over 10 endpoints for my mobile app in only two full days of work. It is concise, easy and very fast.
I will be using Delphi 10.2 throughout this article.
Let’s start
Step 1. Create your project
File-> New -> Other
It will open a window, in the left select Delphi Projects->DataSnap Server
In the right, Select and Create: DataSnap WebBroker Application
Keep pressing Next until the end. You can select all the defaults by now.
Step 2. Check your files
You should have the following Files tree
Project
- FormUnit1.pas
- ServerMethodsUnit1.pas
- WebModuleUnit1.pas
FormUnit1.pas
It is your form, this is where you will start/stop the service and select the port.
ServerMethodsUnit1.pas
We are not going to use this one. This will be used when working with DataSnap. Today it is not the case!
WebModuleUnit1.pas
This is where the magic will happen, here we will create the endpoints and write our code.
Step 3. First Test!
- Go to
WebModuleUnit1.pas
; - Select design to go to your form;
- In Structure Panel in the left do a right click in
Actions
and click inAdd Item
. - A new item will be added in the tree. Click in the Item and go to your Object Inspector to change the properties.
Put the following properties:
MethodType = mtGet
Name = actClients
PathInfo = /clients
MethodType
Here it is where you say if you are going to get, delete, put or post data. In our case we are going to get a list of clients.
Name
This property is only the name. It matters you follow a pattern so your peers will understand your code.
PathInfo
This is your endpoint, people will call your BaseUrl followed by the endpoint.
For example in GitHub API when you call the following URL.
/users
is the endpoint!! :)
Step 4. Configure your response
In the Object Inspector change from properties to Events and double click in OnAction to generate the action procedure.
This will generate a procedure for the action we are working on. This is where we are going to write our code that will be the response for the client.
procedure TWebModule1.WebModule1actClientsAction(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
// TODO Write login and send the response
end;
Now, we are going just to write a dumb code to test our server.
procedure TWebModule1.WebModule1actClientsAction(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
Response.Content := '{It worked}';
end;
At last, run and start your server. Call from any browser the following url.
And you should the our dumb code on the screen.
Step 5. Calling MySQL
Now you can work whatever code you want in this action and return any response you want to the user. (This will be probably a JSON response, more tips in next step).
I will not work on connection to MySQL on this article, however I did two articles about that you can check it before keep reading.
Connect MySQL localhost to Delphi using FireDac
Connecting Interbase database sample to Delphi App — FireDac
You can connect a MySQL server, either local, remote or Interbase samples and call a table (in our case it would be a table of clients). After all you would add all the columns you got in a JsonObject
and send as the response.
Step 6. Example and more about JSON
Here you will check an example and you will learn how to create and the response in JSON
. Of course, this connection won’t work for you because I am calling my localhost.
procedure TWM.WMactLoteamentosAction(Sender: TObject; Request: TWebRequest;
Response: TWebResponse; var Handled: Boolean);
var
qryClients: TFDQuery;
JsonArray: TJSONArray;
JsonObject: TJSONObject;
begin
// Configure response
Response.ContentType := 'application/json; charset=utf-8'; // Search for my clients table
qryClients:= TFDQuery.Create(nil);
with qryClients do
begin
Connection := FDConnection;
Active := False;
SQL.Clear; Open('SELECT * FROM clients'); if qryLoteamentos.RecordCount > 0 then // If there are items
begin
JsonArray := TJSONArray.Create;
try
First;
while not Eof do // Iterate all items in the FDQuery
begin
JsonObject := TJSONObject.Create;
AddFieldsToJSON(JsonObject, qryLoteamentos);
JsonArray.AddElement(JsonObject);
Next;
end;
finally
Response.Content := JsonArray.ToString;
JsonArray.DisposeOf;
end;
end;
end;
end;procedure AddFieldsToJSON(AJsonObject: TJSONObject;
AQuery: TFDQuery);
begin
with AQuery do
begin
AJsonObject.AddPair('id', TJSONNumber.Create(FieldByName('id').AsInteger));
AJsonObject.AddPair('name', FieldByName('name').AsString);
AJsonObject.AddPair('country', FieldByName('country').AsString);
end;
end;
This would get a response like that:
[
{
"id": 1,
"name": "Maria Eduarda",
"country": "Brazil"
},
{
"id": 2,
"name": "Maria Clara",
"country": "Brazil"
},
{
"id": 3,
"name": "Maria Vitória",
"country": "Brazil"
}
]
To understand the structure, the [] indicates a JSONArray
and the {} indicates a JSONObject
.
Black is the array and Blue are the JSONObjects.
Additional
In case you are thinking about how to send parameters to your server. I will teach you right now.
Query Parameters
For searching query parameters you just need to call Request.QueryFields
.
Let’s take the following url: http://localhost:8080/clients?id_client=1
if Request.QueryFields.Count > 0 then
ClientID := Request.QueryFields.Values['id_client'];
Body Parameters
If you want to send parameters in the body you can send it as a Json. For example if you send the following body.
{
"name": "Maria Eduarda",
"country": "Brazil"
}
You could get the fields with the following code.
var
RequestObject: TJSONObject;
Name, Country: string;
begin
RequestObject := TJSONObject.ParseJSONValue(Request.Content) as TJSONObject;
Name := RequestObject.GetValue('name').Value;
Country := RequestObject.GetValue('country').Value;
end;
Happy coding!