X
X

Login

Login if you already have an account

LOGIN

Register

Create a new account. join us!

REGISTER

Support

Need some help? Check out our forum.

FORUM

FYI – FatFractal Server Extensions lets you extend your API with any function that you want


As a developer, I want to be able to add any function without limitation to my API so that I can… do just about anything!

As Gary mentioned in his post about the origins and future of FatFractal’s NoServer -

The cloud should… Not prevent me from doing anything else that I want to do”

Server Extensions are, essentially, a means to extend your API with any kind of function that you desire. Server Extensions accept data as needed, execute any code that you want and return a broad set of return types (JSON, HTML) allowing virtually unlimited capabilities for your backend. They are easy to create, and you can add as many as you wish.

What can I do with a Server Extension?

The uses for Server Extensions are very broad, but a few examples are:

  • Aggregate data on the fly without corrupting your data model.
  • Access other backend services (e.g. salesforce, sap, etc.), then transform/ return the results.
  • Data management/administrative functions.
  • Manipulate and return HTML, images, videos, documents or any other MIME type.

Extending your API

Accessing a server extension is as simple as naming it in your FFDL (what’s this?), which will provide URI access to this particular function.

CREATE EXTENSION /extension_name AS javascript:require (‘scripts/MyExtensions.js’).function_to_be_executed();

This will add a new URI endpoint to your application that looks like:

https://mydomain.fatfractal.com/ff/ext/extension_name

When that URI is called, the function function_to_be_executed that is in the file MyExtensions.js in the ff-scripts directory will be called. Any provided parameters or data are made available to the function as well. You also have the option to declare the function to be secured (default) or add UNSECURED which allows a non-authenticated user to call the function as desired.

Passing in Data

There is a wealth of data from a request that is made available to a Server Extension, including:

httpMethod: the HTTP method (eg. GET, POST, PUT, DELETE, HEAD)
httpRequestUri: the request URI, relative to your application’s base URL
httpParameters: A map of the request parameters
httpHeaders: A map of the request headers
httpCookies: For convenience, a map of the cookies from the Cookie request header
httpContent: A map corresponding to the JSON content supplied in the request body, if any
ffUser: the guid of the logged-in user

This means that you can process according to the httpMethod used, pass in data as httpContent or as URL parameters and authenticate based on the user making the request – in short, you have a lot of flexibility on getting what you want into a Server Extension.

Return Types

You also have control over what gets returned by the extension, including the following:

result: the data or content that you wish to return
responseCode: the appropriate http response code
statusMessage: an informational status message useful for debugging
mimeType: the MIME type of the response content

One of the most useful abilities that Server Extensions provide is the additional return MIME types that are supported. For example, you could create an image resizing service and set the MIME type of the return (e.g. “image/jpeg” or “image/png”). Or, you could read an html template file, replace elements to personalize it and return a web page (“text/html”). And, of course, you can always return data as well (“application/json”), which is the default.

You can also implement as much error handling as you want based on what data is received as well as the result of the operation itself. For example, checking for required information and returning an appropriate error code with a message that you want.

The following example of an extension that validates a user registration from a link shows a number of these features in use:

exports.verifyRegistration = function() {
var data = ff.getExtensionRequestData();
var hc = require('ringo/httpclient');
var r = ff.response();
// check if user guid provided
var guid = data.httpParameters['guid'];
if (! guid) {r.result = null;
r.responseCode = "400";
r.statusMessage = "ActivationRequest guid not supplied";
r.mimeType = "text/html";
return;
}
// check if activationRequest exists
var activationRequest = ff.getObjFromUri("/ff/resources/ActivationRequest/" + guid);
if (! activationRequest) {
var htmlContent = hc.get(ff.getHttpAppAddress() + '/validateuser.html').content;
htmlContent = htmlContent.replace("___SUBJECT___", "ERROR");
htmlContent = htmlContent.replace("___MESSAGE___", "The validation request for this account no longer exists. ";
htmlContent = '' + htmlContent;
r.result = htmlContent;
r.responseCode = "404";
r.statusMessage = "ActivationRequest could not be found";
r.mimeType = "text/html";
return;
}
// check if user exists
var user = ff.getUser(activationRequest.userGuid);
if (! user) {
r.result = null;
r.responseCode = "404";
r.statusMessage = "User could not be found";
r.mimeType = "text/html";
return;
}
// checks passed - now create the welcome html from a template and return
user.active = true;
ff.updateObj(user);
ff.deleteObj(activationRequest);
r.responseCode = "200";
var htmlContent = hc.get(ff.getHttpAppAddress() + '/validateuser.html').content;
    htmlContent = htmlContent.replace("___SUBJECT___", "Thank You!");
htmlContent = htmlContent.replace("___MESSAGE___", "Your account has been activated.";
htmlContent = '' + htmlContent;
r.result = htmlContent;
r.statusMessage = "User now activated";
r.mimeType = "text/html";
}

Hope you find this useful…

Kevin

For more information about Server Extensions, see the docs here.

For more information about FFDL, see here.

Contact