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.

PaaS? BaaS? What?

Lots of people ask about the origins of NoServer, which is what we call FatFractal’s BaaS module.

We were in the process of building out our cloud fabric and one night, while building yet another demo app, I decided that all developer-centric cloud platforms really also ought to offer a way for developers to get 90% of what they need for the server-side of their app, out-of-the-box, while also trying to ensure that we not fence them in – i.e. give lots of functionality with minimum effort whilst also giving flexibility and extensibility to go beyond the box as you reach the edges of what is initially provided.

The 90% boiled down to the following. The cloud should:

  • Store and retrieve my objects.
  • Securely – permissions and security should be robust and at a fundamental level.
  • Efficiently – with easy to create queries that get me what I want.
  • Execute code on the backend when my data changes (events).
  • Not prevent me from doing anything else that I want to do.



The last point is really important! Whilst getting the other things makes my life a lot easier and will make me very happy for a month or two, if the flip side is that I then get stuck and as a result get frustrated and miserable, then I wouldn’t want it. So by June 2012 we had built enough to trial with customers – who loved it! – we launched our public beta in September, worked through the kinks in Oct-Dec :-) and we are now really focussed on getting the word out.

Meanwhile, some new marketing terms were emerging from other similar, but essentially different approaches. Platform as a Service (PaaS) and Backend as a Service (BaaS) are now terms that are used widely.

Upon reflection, it seems to me that they are both missing the point. PaaS is still very focused on a historical view of a set of IT problems, i.e. “stacks”. BaaS is seeking to provide more of a turnkey solution for application developers that treats the backend as a black box and is extremely limiting, invasive and prescriptive (smells like attempts at lock-in to me).

IMHO – what the market needs is a bit of both: a very smart cloud fabric that deals with infrastructure, monitoring, scalability, reliability, resilience etc, and also provides the ease of creation and out-of-the-box features that BaaS does, but does not limit the developer as a result. If I want to deploy some Java Code, Ruby Code or anything else in order to do something that I want to do, right alongside my “BaaS” stuff, then I should be able to.

So – in a nutshell, what we have so far built into NoServer is:

  • True fully qualified REST URIs
  • CRUD persistence
  • SDKs that operate at the data level and do not encroach into your code unnecessarily.
  • Amazingly straightforward modelling of your object graph’s relationships
  • Natural language, chained queries nested as deep as you want.
  • Strong authentication. SSL of course. Declarative access controls for your data which is sufficient for almost all use cases while also providing programmatic control (directly setting ACLs on objects) for when the declarative approach isn’t enough (which, so far, has been incredibly rare)
  • Exposed CRUD events with defined Event Handlers that execute your custom JavaScript code when they occur with synchronous (PRE or POST) as well as asynchronous modes. Currently we use RingoJS which allows you to do pretty much anything you need to do, including make HTTP requests; we also supply an API for sending Apple/Android push notifications, sending emails, image processing, and of course full access to your app’s datastore.
  • Server Extensions that allow you to extend your API with whatever server-side processing you want, and the ability to schedule scripts to run whenever you like



We’re pretty flexible at the server-side already, and I think you’ll agree we’re already better than (or *at least* as good as!) our BaaS competitors, but there’s lots more to come. Here’s a list of some of what’s coming over the next six months or so!

  • Greatly enhanced and pluggable authentication framework so that you can script integration with pretty much whatever 3rd-party identity / authentication cloud you like
  • Event Handlers for GET requests, and ‘virtual’ collections
  • Allowing mix and match of the powerful declarative access controls we already have with your own javascript for the really really edge cases (like, only allow access to this object if the current user lives in Idaho)
  • Enabling integration between NoServer and Rails backends. This is a big step towards completing our vision – i.e. if you reach the limits of what NoServer provides, then you should be able to extend your backend with some Ruby-on-Rails, or Java servlets, or NodeJS, or whatever
  • Allowing use of NodeJS modules in your NoServer server-side scripting

  • Full support for NodeJS applications on the FatFractal PaaS, and integration between NoServer / Node / Rails / Servlets modules in your app’s backend
  • And last, but definitely not least – and probably the most personally exciting to me given where I have spent a lot of my working life (i.e. large enterprise IT) – we will be working on evolving our products so that they can be leveraged by enterprises. More on that when the time comes :-)



I hope that you like what we have built – would very much appreciate your feedback.

Cheers,

Gary

In case you’re curious – NoServer is a tribute to the no-stuff (chamber, room, globe, ship) in Frank Herbert’s most excellent Dune series.

FYI – With FatFractal you can send text or html emails programmatically using our JS Server-side SDK.

As a developer, I want to be able to easily send emails from my backend so that I can validate users, create email reports and alert others to important information


There are many use cases where sending an email from your application backend. One is to notify someone when some data has changed. Another is for the purposes of validating a user. This post will cover how to do both with your FatFractal backend.

Text-only emails

The sendSMTPEmail method (docs) will send text-only email messages from an account that you specify. For example, if you want to send a notification email to alert you when a new object is stored – say an Order, is received by your app.

First, define an EventHandler (what’s this?) as follows that will extract info from the new Order object, get some additional information from your backend and the create a notification email to whomever you want to alert them that a new order was created. This should go in a file in the ff-scripts directory that was created when your app was created (more about this), in this case we will call it EventHandlers.js.

function notifyNewOrder() {
var order = ff.getEventHandlerData();
var user = ff.getObjFromUri("ff/resources/FFUser/" + order.createdBy);
var name = user.firstName + " " + user.lastName;
var msgSubject = "New Order notification";
var msgString = "Order " + order.amount + " was created by " + name;
ff.sendSMTPEmail("<mailserver>", "465", "true", "465", “<username>”, “<password>”, “<fromAddress>”, “<toAddress>”, msgSubject, msgString);
}

In your FFDL (what’s this?), you then define your EventHander like this:

CREATE HANDLER notifyNewOrder ASYNC ON /Order CREATE AS javascript:require (‘scripts/EventHandlers.js’).notifyNewApp();

HTML emails

The sendEmail method (docs) accepts a set of parameters and will send your html content via an email account that you specify. For this example, we will use a slightly more complicated example – we will send out

function sendWelcomeEmail() {
var user = ff.getEventHandlerData();
var subject = “Welcome to Foo - we are so glad you joined us”;
var html = getHtmlWelcomeMessage(user);
try {
var emailData = {
host:"<mailserver>",
port:"<port>",
auth:<true/false>,
authPort:"<port>",
username:"<username>",
password:"<password>",
from:"<fromAddress>",
to:user.email,
subject:subject,
text:text, html:html
};
emailData = JSON.parse(JSON.stringify(emailData));
ff.sendEmail(emailData);
} catch (error) {
throw "Caught exception: " + error + " while sending email";
}
}

And, include the FFDL for this EventHandler as well.

CREATE HANDLER validateUser POST ON /FFUser CREATE AS javascript:require (‘scripts/EventHandlers.js’).sendWelcomeEmail();

The above makes use of a function called getHtmlWelcomeMessage which fetches a template HTML file that I have included in the webapp directory of my app, replaces marked elements with personalized content and returns the HTML content using the http client that is available to your server side js code.

function getHtmlWelcomeMessage (user) {
var hc = require('ringo/httpclient');
var htmlMessage = hc.get(ff.getHttpAppAddress() + '/welcome_email.html').content;
htmlMessage = htmlMessage.replace("___FIRST_NAME___", user.firstName);
htmlMessage = htmlMessage.replace("___LAST_NAME___", user.lastName);
return '' + htmlMessage;
}

That’s it – super easy to send email content to your users or for internal notifications/ reports or whatever you want!

Happy coding!

Kevin

For more details about FFDL, the documentation is here.

For more details about the Server-side JS SDK, the documentation is here.

For more about EventHandlers, the documentation is
Event Handers Reference

Contact