(Originally published on the DataFlex Wiki)
6 of 6
The simple example of a RESTful service set out in the article A Simple RESTful Service involved quite a bit of work to produce an API for only one table. An alternative approach for you, is using the DataFlex REST library I have created, which can be downloaded from here.
To use it, unzip that file into some directory, then, from the workspace you are developing in, use that as a library; in the Studio choose: Tools -> Maintain Libraries… -> Add Library, then navigate to where you unzipped it and within it select the “RESTLibrary.sws” file.
That will add a new section to the Studio’s Class Palette entitled “REST”.
With the WebApp project selected in the Studio, choose: File -> New -> Other -> DataFlex Source File, naming it, for this example, “WebOrderAPI”, which will create a blank package file. Into that, from the new REST section of the class palette, drag an object of the cRESTfulService class. Rename the object oWebOrderAPI.
Then again choose: File -> New -> Other -> DataFlex Source File, this time naming it ApiCustomersHandler. Into that blank file drag an object of the cRestResourceHandler class. Change the object’s name to oApiCustomersHandler and set its psInterfacePath property (an empty string by default) to “customers“.
Then in the DDO Explorer pane (lower-right in the Studio by default) click the “+” book icon (Add DDO: ) and select the cCustomerDataDictionary.
Drag a cRESTApiObject from the class palette to below the comment “Add your cRESTApiObjects here“. Rename it to “oCustomers”. Set its phoDD property to oCustomer_DD, its psCollName (collection name) property to “customers” (plural) and its psInstName (instance name) property to “customer” (singular).
Uncomment one of the “Send AddListColumn” lines and change its “Table.Column” to Customer.Customer_Number, then copy that line and make the copy for Customer.Name. (You can keep adding those to your heart’s content, but lists should be sparing of such detail.)
Go back to your WebOrderAPI file and under the comment line: ‘Add “Use” statements for your cResourceHandler objects here:’ add the line: “Use APICustomersHandler.pkg“.
For development you may want to change the pbVerboseErrors setting to True, although for deployment it should probably be set back to False, to avoid confusing users with a pile of technical detail, which they neither should, nor want to, be exposed to.
You should perhaps, for future-proofing a real API, change the psPath setting from its default of “api” to “api/v1” (to provide for v2, v3 and so on in the future) – Note: this will change the URL which you use to make calls to it.
That should leave you with (some additional comments are mine):
Use cRESTfulService.pkg Object oWebOrderAPI is a cRESTfulService Set psPath to "api/v1" // Changed to provide for future versions Set pbVerboseErrors to True // For development only, return to False for deployment // Add "Use" statements for your cResourceHandler objects here: Use APICustomersHandler.pkg // You add this line Procedure APIRoot Handle hoResp Get CreateJsonObject to hoResp Send AddRegisteredCollections hoResp Send OutputJson hoResp End_Procedure Procedure ProcessHttpRequest String sVerb String sPart0 Get PathPart 0 to sPart0 Move (Lowercase(sPart0)) to sPart0 Case Begin Case ((sVerb = C_httpGet) and (sPart0 = "")) Send APIRoot Case Break Case (IsRegisteredPath(Self, sPart0)) Send AutoProcess sPart0 Case Break Case Else Send UnrecognisedOperation Case Break Case End End_Procedure End_Object
The overall structure with your web app will be something like this (although the diagram includes additional cRESTResourceHandler objects and cRESTApiObjects, making up a fuller API):
This example does not have any security built into it yet, but the cRESTfulService class does understand a bit about Basic Auth, so we can add the following short OnPreRequest procedure to the oWebOrderAPI object:
Procedure OnPreRequest String sVerb String sPath tBasicAuthCredentials tCreds Boolean bOK Set psUsername to "" // Reset it to blank at the start of *every* request Get BasicAuthCredentials to tCreds If (tCreds.sUserName <> "") Begin Clear WebAppUser Move tCreds.sUserName to WebAppUser.LoginName Find Eq WebAppUser by Index.1 If (Found) Begin Move (ComparePasswords(ghoWebSessionManager, Trim(WebAppUser.Password), ; tCreds.sPassword)) to bOK If bOK ; Set psUsername to tCreds.sUserName End End End_Procedure
As you can see, that relies on the ComparePasswords function of the WebSessionManager object, which will not be present in a Basic Web Project, so if using such, you would have to replace that, perhaps with a simple:
Move (Trim(WebAppUser.Password) = Trim(tCreds.sPassword)) to bOK
Which assumes that you are not using encrypted passwords, however how to handle those is left as an exercise for the reader!
Then at the top of the file add “Open WebAppUser“, while at the top of the oWebOrderAPI object add “Property String psUsername“.
Finally, right at the beginning of the ProcessHttpRequest procedure add:
If (psUsername(Self) = "") Begin Send BasicAuthRequired "Web Order API" Procedure_Return End
Fuller instructions for creating an API using the DataFlex REST library can be found in my course notes from Synergy 2019, although complete documentation for the library has sadly yet to make it to the top of my ToDo pile (it will be a lot of work).
6 of 6