This Function Development Kit makes it easy to deploy Node.js functions to Fn.
Writing a Node.js function is simply a matter of writing a handler function that you pass to the FDK to invoke each time your function is called.
Start by creating a node function with fn init and installing the FDK:
fn init --runtime node nodefunc
cd nodefuncThis creates a simple hello world function in func.js:
var fdk = require('@fnproject/fdk');
fdk.handle(function(input) {
var name = 'World';
if (input.name) {
name = input.name;
}
response = {'message': 'Hello ' + name}
return response
})The handler function takes the string input that is sent to the function and returns a response string. Using the FDK you don't have to worry about reading input from standard input and writing to standard output to return your response. The FDK let's you focus on your function logic and not the mechanics.
Now run it!
fn runNow you have a basic running Node function that you can modify and add what you want.
From this point on, it's the same as any other function in any language. deploy the function:
fn deploy --app fnfdk --localOnce deployed, you and invoke the function:
echo -n "Tom" | fn call fdkdemo /helloor
curl -d "Tom" http://localhost:8080/r/fdkdemo/helloIn both cases you'll get the response:
Hello Tom from Node!Function invocation context details are available through an optional function argument.
To receive a context object, simply add a second argument to your handler function.
in the following example the call_id is obtained from the context and included in
the response message:
var fdk = require('@fnproject/fdk');
fdk.handle(function(input, ctx) {
var name = 'World';
if (input) {
name = input;
}
return 'Hello ' + name + ' from Node call ' + ctx.callId + '!';
})In the case of default format functions the context give you access to all environment variables
including those defined through function or app config as well as those automatically provided
by Fn like app_name, path, memory, etc.
You return an asynchronous response from a function by returning a Javascript Promise from the function body:
var fdk = require('@fnproject/fdk');
fdk.handle(function(input, ctx) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve("Hello"), 1000);
});
})By default the FDK will convert input with a content-type matching application/json into a JSON object as the function input, if the incoming content type is different from application/json then the input will be the raw string value of the input. In both cases, the raw (string) version of the input is also available in ctx.body.
Likewise by default the output of a function will be treated as a JSON object and converted using JSON.stringify - you can change this behaviour by setting the content type of the response in the context using ctx.responseContentType='application/text-plain'. Changing the content type to non-json will result in the output being treated as a string.
You can read http headers passed into a function invocation using ctx.protocol.header(key), this returns the first header value of the header matching key (after canonicalization) and ctx.protocol.headers which returns an object containing all headers.
var fdk = require('@fnproject/fdk');
fdk.handle(function(input, ctx) {
console.log("Authorization header:" , ctx.protocol.header("Authorization"))
console.log( ctx.protocol.headers) // prints e.g. { "Content-Type": ["application/json"],"Accept":["application/json","text/plain"] }
})Outbound headers and the HTTP status code can be modified when the function uses the json request format.
To update the outbound status-code set ctx.protocol.statusCode. To modify outbound headers use ctx.protocol.setHeader(k,v) or ctx.protocol.addHeader(k,v) which set (overwriting existing headers) or add (preserving existing headers) headers to the response respectively.
var fdk = require('@fnproject/fdk');
fdk.handle(function(input, ctx) {
ctx.protocol.setHeader("Location", "http://example.com")
ctx.protocol.statusCode = 302
})Fn handles Node.js dependencies in the following way:
- If a
package.jsonis present without anode_modulesdirectory, an Fn build runs annpm installwithin the build process and installs your dependencies. - If the
node_modulesis present, Fn assumes you have provided the dependencies yourself and no installation is performed.