Scripting

From DreamFactory
Jump to: navigation, search
(Adding HTTP headers, query parameters, or cURL options to api calls)
(Adding HTTP headers, query parameters, or cURL options to api calls)
Line 221: Line 221:
 
         var result = JSON.parse(body);
 
         var result = JSON.parse(body);
 
         console.log(result);
 
         console.log(result);
 +
}
 
</source>
 
</source>
  

Revision as of 17:24, 9 November 2016

DreamFactory supports server-side scripting to quickly and easily customize almost all of the platform's REST API endpoints to include business logic on the server, such as field validation, workflow triggers, runtime calculations, and more. Developers can easily attach scripts to any existing API endpoint, for both pre- and post-processing of the request and response. You can also write your own custom REST APIs with server-side script services. Starting with release 2.3.0, scripts can even be queued for later processing.

Supported Scripting Languages

DreamFactory scripting supports several modern scripting languages. To get a list of which ones are installed and setup on a particular instance use the following API.

http:/example.com/api/v2/system/script_type
{
  "resource": [
    {
      "name": "nodejs",
      "label": "Node.js",
      "description": "Server-side JavaScript handler using the Node.js engine.",
      "sandboxed": false
    },
    {
      "name": "php",
      "label": "PHP",
      "description": "Script handler using native PHP.",
      "sandboxed": false
    },
    {
      "name": "python",
      "label": "Python",
      "description": "Script handler using native Python.",
      "sandboxed": false
    },
    {
      "name": "v8js",
      "label": "V8js",
      "description": "Server-side JavaScript handler using the V8js engine.",
      "sandboxed": true
    }
  ]
}

Note: The sandbox setting means that the script execution is bound by memory and time and is not allowed access to other operating system functionalities outside of PHP's context. This is currently only the case for V8Js. Therefore, be aware that DreamFactory cannot control what is done inside scripts using non-sandboxed languages on a server.

The following are typically supported on most installs:

Where Scripts Can Be Used

Server-side scripts can currently be used in two areas of a DreamFactory instance: system events triggered by API calls and customized script services.

Resources Available To A Script

When a script is executed, DreamFactory passes in two very useful resources that allow each script to access many parts of the system including system states, configuration, and even a means to call other services or external APIs. They are the event resource and the platform resource.

Note: The term "resource" is used generically here, based on the scripting language used, the resource could either be an object (i.e. V8js or Node.js) or an array (i.e. PHP).

The Event Resource

The event resource contains the structured data about the event triggered (Event Scripting) or from the API service call (Script Services). As seen below, this includes things like the request and response information available to this "event".

Note: Determined by the type of event triggering the script, parts of this event resource are writable. Modifications to this resource while executing the script do not result in a change to that resource (i.e. request or response) in further internal handling of the API call, unless the event script is configured with the allow_event_modification setting to true, or it is the response on a script service. Prior to 2.1.2, the allow_event_modification was accomplished by setting a content_changed element in the request or response object to true.

The event resource has the following properties:

Property Type Description
request resource A resource representing the inbound REST API call, i.e. the HTTP request.
response resource A resource representing the response to an inbound REST API call, i.e. the HTTP response.
resource string Any additional resource names typically represented as a replaceable part of the path, i.e. "table name" on a db/_table/{table_name} call.

Event Request

The "request" resource contains all the components of the original HTTP request. This resource is always available, and is writable during pre-process event scripting.

Property Type Description
api_version string The API version used for the request (i.e. 2.0).
method string The HTTP method of the request (i.e. GET, POST, PUT).
parameters resource An object/array of query string parameters received with the request, indexed by the parameter name.
headers resource An object/array of HTTP headers from the request, indexed by the lowercase header name.
content string The body of the request in raw string format.
content_type string The format type (i.e. "application/json") of the raw content of the request.
payload resource The body (POST body) of the request, i.e. the content, converted to an internally usable object/array if possible.

Any allowed changes to this data will overwrite existing data in the request, before further listeners are called and/or the request is handled by the called service.

Event Response

The response resource contains the data being sent back to the client from the request.

Note: This resource is only available/relevant on post-process event and script service scripts.

Property Type Description
status_code integer The HTTP status code of the response (i.e. 200, 404, 500, etc).
headers resource An object/array of HTTP headers for the response back to the client.
content mixed The body of the request as an object if the content_type is not set, or in raw string format.
content_type string The content type (i.e. json) of the raw content of the request.

Just like request, any allowed changes to response will overwrite existing data in the response, before it is sent back to the caller.

The Platform Resource

This platform resource may be used to access configuration and system states, as well as, the REST API of your instance via inline calls. This makes internal requests to other services directly without requiring an HTTP call.

The platform resource has the following properties:

Field Type Description
api resource An array/object that allows access to the instance's REST API.
config resource An array/object consisting of the current configuration of the instance.
session resource An array/object consisting of the current session information.

Platform API

The api resource contains methods for instance API access. This object contains a method for each type of REST verb.

Function Description
get GET a resource
post POST a resource
put PUT a resource
patch PATCH a resource
delete DELETE a resource

They all accept the same arguments:

method( "service[/resource_path]"[, payload[, curl_options]] );
  • method - Required. The method/verb listed above.
  • service - Required. The service name (as used in API calls) or external URI.
  • resource_path - Optional depending on your call. Resources of the service called.
  • payload - Optional, but must contain a valid object for the language of the script.
  • curl_options - Optional for external calls only.

Calling internally only requires the relative URL without the /api/v2/ portion:

// Retrieve all records from the 'Contacts' table in the 'db' database service
platform.api.get( "db/_table/Contacts" );

You may also pass absolute URLs to these methods to retrieve external resources:

platform.api.get( "http://www.google.com" );

or

platform.api.post( "https://www.example.com/api/something_cool", {"cool":"very"} );


Adding HTTP headers, query parameters, or cURL options to api calls

You can specify any combination of headers and query parameters when calling platform.api functions. This is supported by all script types using the 'options' argument.

// V8js
 
var url = 'http://example.com/my_api';
var payload = JSON.stringify({"name":"test"});
var options = {
    'headers': {
        'Content-Type': 'application/json'
    },
    'parameters': {
        'api_key': 'my_api_key'
    },
};
var result = platform.api.post(url, payload, options);
var_dump(result);
// Node.js
 
var url = 'http://example.com/my_api';
var payload = {"name":"test"};
var options = {
    'headers': {
        'Content-Type': 'application/json'
    },
    'parameters': {
        'api_key': 'my_api_key'
    },
};
platform.api.post(url, payload, options, function(body, response) {
        var result = JSON.parse(body);
        console.log(result);
}
// PHP

$url = 'http://example.com/my_api';
$payload = json_decode("{\"name\":\"test\"}", true);
$options = [];
$options['headers'] = [];
$options['headers']['Content-Type'] = 'application/json';
$options['parameters'] = [];
$options['parameters']['api_key'] = 'my_api_key';
$api = $platform['api'];
$post = $api->post;
$result = $post($url, $payload, $options);
var_dump($result);
// Python
 
url = 'http://example.com/my_api'
payload = '{\"resource\":[{\"name\":\"test\",\"complete\":false}]}'
options = {}
options['headers'] = {}
options['headers']['Content-Type'] = 'application/json'
options['parameters'] = {}
options['parameters']['api_key'] = 'my_api_key'
result = platform.api.post(url, payload, options)
data = result.read()
print data
jsonData = bunchify(json.loads(data))

For V8js and PHP scripts, which use cURL to make calls to external URLs, you can also specify any number of cURL options: Calls to internal URLs do not use cURL, so cURL options have no effect there.

// V8js
 
options = {
    'headers': {
        'Content-Type': 'application/json'
    },
    'CURLOPT_USERNAME' : '[email protected]'
    'CURLOPT_PASSWORD' : 'password123'
};
// PHP

$options = [];
$options['headers'] = [];
$options['headers']['Content-Type'] = 'application/json';
$options['parameters'] = [];
$options['parameters']['api_key'] = 'my_api_key';
$options['CURLOPT_USERNAME'] = '[email protected]';
$options['CURLOPT_PASSWORD'] = 'password123';

cURL options can include HTTP headers using CURLOPT_HTTPHEADER, but it's recommended to use options.headers for V8js or $options['headers'] for PHP to send headers as shown above.

Platform Config

The config object contains configuration settings for the instance.

Function Description
df Configuration settings specific to DreamFactory.
       (
           [version] => "2.1.0"
           [api_version] => "2.0"
           [always_wrap_resources] => true
           [resources_wrapper] => "resource"
           [storage_path] => "my/install/path/storage"
           ...
       )

Platform Session

The session resource contains information and states about the current session for the event.

Function Description
api_key DreamFactory API key.
session_token Session token, i.e. JWT.
user User information derived from the supplied session token, i.e. JWT.
       (
           [id] => 6
           [display_name] => First Last
           [first_name] => First
           [last_name] => Last
           [email] => [email protected]
           [is_sys_admin] => 1
           [last_login_date] => 2016-02-19 14:05:25
       )
app App information derived from the supplied API key.
lookup Available lookups for the session.

Stopping Script Execution

Just like in normal code execution, execution of a script is stopped prematurely by two means, throwing an exception, or returning.

// Stop execution if verbs other than GET are used in Custom Scripting Service
if (event.request.method !== "GET") {
    throw "Only HTTP GET is allowed on this endpoint."; // will result in a 500 back to client with the given message.
}
 
// Stop execution and return a specific status code
if (event.resource !== "test") {
    event.response.status_code = 400;
    event.response.content = {"error": "Invalid resource requested."};
    return;
}
 
// defaults to 200 status code
event.response.content = {"test": "value"};