Webtask

Documentation

Programming model

Three types of webtasks you can run

For customized documentation and ready to run samples, please log in.

Simple function

In the simplest mechanism, you must provide JavaScript code that returns a function which accepts a single argument: a callback. To indicate completion, the function must call the callback with two arguments: an error, and the result.

module.exports = function(cb) {
    cb(null, { i_am: 'done '});
}        

When the callback is invoked, the result value or an error will be serialized as JSON and sent back to the caller as application/json content type.

Function with context

A more advanced version of the programming model allows you to return a function that accepts two arguments: a context and a callback.

module.exports = function(context, cb) {
    cb(null, { hello: context.data.name || 'Anonymous' });
}        

The context parameter is a JavaScript object with data, query, secrets, and optionally body properties. It also offers the context.storage.get and context.storage.set APIs to access durable storage.

The context.data is a JavaScript object that combines parameters passed to the code using one of several machanisms:

  • The ectx claim of the webtask token.
  • The pctx claim of the webtask token.
  • The URL query parameters of the request.
  • If the pb and mb claims of the webtask token are both set, the key value pairs passed in the request body.

The context.query property is a hash of URL query parameters.

The context.secrets property contains decrypted secrets associated with your webtask at creation time.

Lastly, the context.body is JavaScript representation of a parsed application/json or application/x-www-form-urlencoded request body. It is only present for requests with bodies of appropriate content type when the pb claim of the webtask token is set to 1.

Full HTTP control

The most flexible programming model allows you to take full control over the HTTP request and response.

module.exports = function (context, req, res) {
    res.writeHead(200, { 'Content-Type': 'text/html '});
    res.end('<h1>Hello, world!</h1>');
}        

The context argument behaves the same way as in the two simpler programming models. The body of the request will be unconsumed unless the pb claim of the webtask token is set to 1. Note that this programming model does not have a concept of a callback. Ending the HTTP response indicates completion.

Custom programming models

In order to offer a programming model different from one of the three that are built-in, a programming model adaptation layer must be built. To avoid implementing this adaptation layer within webtask script itself, we introduced the webtask compiler concept.

Webtask compilers enable webtasks to be written in domain specific languages, such as Node.js functions with custom signatures, Express, C#, T-SQL, and many more. The webtask compiler concept introduces a first class "compilation" step for a webtask script. Webtask compiler is declaratively associated with a webtask script at creation time, which enables webtask script to focus exclusively on domain specific programming model.

You can read more about the webtask compiler concept and how to implement one here.

Example: Express

Let's see the code for a basic Hello World example using Express. The webtask script, in a hello.js file, would be:

var app = new (require('express'))();
app.get('/', (req, res) => res.send('Hello World'));
module.exports = app;

Notice how it exports the Express application directly rather than a function matching one of the three basic webtask programming models. We have just written a webtask that uses a custom programming model based on Express.

Note that when using the Express programming model, the webtask context is available as req.webtaskContext within the connect handlers.

The webtask compiler code, in auth0/webtask-tools module, would be:

exports.express = function (options, cb) {
  options.nodejsCompiler(options.script, function (error, func) {
    if (error) return cb(error);
    try {
      func = fromConnect(func); // this is where adaptation happens
    }
    catch (e) {
      return cb(e);
    }
    return cb(null, func);
  });
};

In order to create a webtask using the webtask script and compiler above, the following command can be used:

$ wt create hello.js --meta wt-compiler=webtask-tools/express

Notice how the webtask script in the hello.js file is associated with the webtask compiler implemented by the express method of the webtask-tools module. The compiler method is invoked at runtime to compile the webtask script when a request to execute this webtask is made.

Example: C#

Let's look into another simple example using C#. The webtask code, in the hello.cs file, would be:

async (dynamic ctx) => {
  return "Hello, " + ctx.query.name.ToString();
}

Notice how the webtask script is implemeted using an async lambda expression in C#.

The compiler code that uses the Edge.js module to embed C# code in a Node.js application is available in the auth0/webtask-tools module:

exports.cs = function (options, cb) {
  cb(null, require('edge').func(options.script));
};

In order to create the webtask, the following command can be used:

$ wt create hello.cs --name hello --meta wt-compiler=webtask-tools/cs

When the webtask is executed, the compiler code will use Edge.js module to perfom on-the-fly compilation of the C# webtask script and create a Node.js wrapper around it that matches one of the basic webtask programming models.