Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Database Table Endpoint Obfuscation Through Custom Scripting

DZone's Guide to

Database Table Endpoint Obfuscation Through Custom Scripting

If you're a DreamFactory user, you might have come across the need to customize the otherwise-automated generated endpoint names.

· Integration Zone
Free Resource

Share, secure, distribute, control, and monetize your APIs with the platform built with performance, time-to-value, and growth in mind. Free 90-day trial of 3Scale by Red Hat

DreamFactory’s power lies in the automatic generation of API endpoints and its standardization. There are times, however, where you need something a little more custom, and that’s why we have scripting engines. Let’s look at a specific use case for custom scripting that we have users ask about a lot.

Let’s say your database was built without user friendliness in mind because it was not originally meant to be exposed this way. Perhaps the database was named appprod01data and all your customer info is in a table called appdata_custinfo04. I sense some raised eyebrows, but this is way more common than you would think. Normally, in DreamFactory, you would access this customer data using the endpoint http://myapi.com/api/v2/appprod01data/_table/appdata_custinfo04, using various HTTP request verbs to access and manipulate the data. It’s a bit long and not terribly descriptive. What if we wanted to shorten this to simply http://myapi.com/api/v2/customers? Well, that’s what I’m going to show you how to do with this custom script.

First step: make sure your appprod01data database is connected as a DreamFactory service, following the standard procedure.

Next, we want to create a new custom script service.

  • Go to Services, and click on Create.
  • Under Service Type, select Script >V8js.

Image title

  • Name the service customers and give it a label and description of your choosing.
  • In the Config tab, paste the script below and save the service.

Here is the script we want to use for this functionality. I’ll post the whole thing and then walk through its parts.

var api_path = 'appprod01data/_table/appdata_custinfo04'; 
var method = event.request.method; 
var options = {}; 
options.parameters = event.request.parameters; 
var result;

if (event.resource && event.resource !== '') { 
    api_path = api_path + '/' + event.resource;
}

if (event.request.payload) { 
    var payload = event.request.payload;
} else {
    var payload = null;
}

switch (method) { 
    case 'GET':
        result = platform.api.get(api_path, null, options);
        break;
    case 'POST':
        result = platform.api.post(api_path, payload, options);
        break;
    case 'PUT':
        result = platform.api.put(api_path, payload, options);
        break;
    case 'PATCH':
        result = platform.api.patch(api_path, payload, options);
        break;
    case 'DELETE':
        result = platform.api.delete(api_path, payload, options);
        break;
    default: 
        result = {"message":"Cannot interpret this call. Invalid verb."};
        break;
}

return result; 

Source.

Let’s look at the pieces.

var api_path = 'appprod01data/_table/appdata_custinfo04'; 
var method = event.request.method;
var options = {};
options.parameters = event.request.parameters; 
var result; 

Here, we are setting the real API path, the one we’re obfuscating with the script. Then, we get the HTTP verb being used so that we can know which function to use below. We then establish the options object and add the incoming parameters. This is so we can pass any parameters in the original call (such as filters or limits) on to the real API call. Lastly, we establish the result variable which will be used to store the result of the real API call and returned to the client.

if (event.resource && event.resource !== '') {
    api_path = api_path + '/' + event.resource;
}

In this conditional block, we check to see if there were additional resources included in the request. If there are, we add them to them to the real API call path. For example, if I wanted a specific record from the table, I would have called customers/45 to get a record with ID 45. We need to pass this on to the real API call, as well.

if (event.request.payload) {
    var payload = event.request.payload;
} else {
    var payload = null;
}

In this conditional block, we check to see if a payload was included in the original call. If so, it is stored in the payload variable. If not, the payload is set to null.

Now the guts of the real API calls:

switch (method) { 
    case 'GET':
        result = platform.api.get(api_path, null, options);
        break;
    case 'POST':
        result = platform.api.post(api_path, payload, options);
        break;
    case 'PUT':
        result = platform.api.put(api_path, payload, options);
        break;
    case 'PATCH':
        result = platform.api.patch(api_path, payload, options);
        break;
    case 'DELETE':
        result = platform.api.delete(api_path, payload, options);
        break;
    default: 
        result = {"message":"Cannot interpret this call. Invalid verb."};
        break;
}
return result;

Here, we use JavaScript case switching to check which verb to use. Based on the original call verb, we use platform.api to call that same verb on the real API path. Payloads and parameters are included. In the rare event that you somehow managed to send a different verb, the script returns an error.

This script should accommodate all standard DreamFactory SQL table use cases, and you access them the same way, just with your shortened friendly endpoint.

A Few Examples

You want to get the customer record with ID 1776 but only the ID and name fields:

GEThttp://myapi.com/api/v2/customers/1776?fields=id,name

Perhaps you want to get all customers whose name starts with "Bo" but only want five records:

GEThttp://myapi.com/api/v2/customers?filter=(name%20LIKE%20'Bo%')&limit=5

Or maybe you need to change the name on record 1776:

PATCHhttp://myapi.com/api/v2/customers/1776

    Payload:
{
    "name":"Samuel Adams"
}

You get the idea. All of your normal SQL table operations are available in their usual ways, only we’ve managed to make the endpoint short and user-friendly.

This script will be posted to the DreamFactory scripts repo. It is only compatible with DreamFactory 2.4 and higher. A version of the script that is compatible with older v2 releases can be found in the repo as well.

Explore the core elements of owning an API strategy and best practices for effective API programs. Download the API Owner's Manual, brought to you by 3Scale by Red Hat

Topics:
integration ,tutorial ,dreamfactory ,api ,obfuscation ,scripting

Published at DZone with permission of Drew Pearce, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}