Developing APIs‎ > ‎Extensibility‎ > ‎

Request Event Handlers

You can do some additional processing and customization using event handlers. API Creator can have any number of event handlers, which API Creator automatically executes at certain points during a request. The following types of event handlers are included: 

  • Request event handlers. API Creator calls these for every request, after it receives the request but before it begins work.
  • Response event handlers. API Creator calls these for every request, before it sends back the (successful) final result to the client.

Create Event Handlers

  1. Go to the Manage, Request Events page.
  2. Click Add.
  3. Complete the fields on the page, and then click Save:
    Event type
    The type of event.
    Options: Request event or Response event
    Event Handler name
    The name for your event handler.
    Code
    The handler operations for this event handler.
    Active
    Select this checkbox.
The following image shows this page:
The event handler is created.

How API Creator Calls Request Event Handlers

When you invoke a request, API Creator:

  1. Authenticates your request.
  2. Calls the request event. API Creator provides these variables in the request event:
     Variable NameDescription
     jsonThe raw JSON string that the client sends, if any. Set only for POST and PUT requests. You can modify this string.
     reqThe request object.
     logThe logger for the current request.
  3. Establishes a connection to your database.
  4. Parses the JSON payload.

Request Examples

The following example rejects all requests on SecretData if they do not use HTTPS:

// Reject all requests on SecretData if they do not use HTTPS
if ("SecretData" == req.resourceName && !req.clientUsesHttps) {
  log.error('SecretData was accessed over HTTP by ' + req.clientAddress);
  throw "This resource must be accessed over HTTPS";
}

The following example removes extraneous data that the client sends but that is not needed:

// Remove extraneous data that the client sends but that is not needed.
if ( ! json) {
    // Only requests with a JSON payload are needed.
    return;
}
var data = JSON.parse(json);
if (Array.isArray(data)) {
    for (var i = 0; i < data.length; i++) {
        delete data[i].uselessData;
    }
}
else {
    delete data.uselessData;
}
// Important: you must serialize the data back to a string if you want to change it
json = JSON.stringify(data);

How API Creator Calls Response Event Handlers

When you invoke a response, API Creator:

  1. Calls your rules.
  2. Calls the response event. API Creator provides these variables in the response event:
    Variable nameDescription
     jsonThe complete response object, which is sent back to the client after the response event handlers (if any) have been executed. You can (carefully) change or replace this object.
    Note: Response events are objects or arrays of objects. For a GET, this is a single object or an array of objects depending on the details of the request. For PUT/POST/DELETE, this is a single object with statusCodetxsummaryrulesummary elements. It may also be an error result. JSON.stringify() must be able to stringify the JSON object.
     reqThe request object.
     logThe logger for the request.
     getResourceA function that returns a JSON array containing the results of a GET of the named resource.
  3. Parses the JSON payload.

Response Examples

A fully worked example (provided in the Logic Sample database) illustrates preparing a partner-specific response by materializing a resource and returning it as the response message. The key pattern is that resource object/attribute aliases are defined to match partner expectations.

For more information:

You can also review the following smaller examples:

/
/ Remove all @metadata sections from the response for a specific table/resource
// Note: This would make it difficult for the client to update the data, but this is only an example.
// This only deals with top-level resources. To remove all
// @metadata sections from a complex resource, use recursion.

// An attribute 'TheVerb' is added to each array object or the single object
// with the name of request verb - GET, PUT, POST, PATCH, DELETE

// get the name used for metadata (configurable by project).
// You CAN convert from the Java string value to a JavaScript string object here
var metadataName = new String(req.metadata_name);

if (Array.isArray(json)) {
    // If the response is an array of objects
    for (var i = 0; i < json.length; i += 1) {
        delete json[i][metadataName];

        // You MUST convert to native JavaScript string
        json[i]['TheVerb'] = new String(req.verb.name());
    }
}
else {
    // The response is a single object
    delete json[metadataName];
    json['TheVerb'] = new String(req.verb.name());
}

In the following code snippet, add the top 30 (by amount_total) purchaseorders where the employee is the sales rep by augmenting each employee in a GET of multiple employees:

// for a GET to an employee, add any PURCHASEORDERS where the employee is a sales rep
if ("GET" == req.verb && "employee" == req.resourceName && json.length) {
   for (var i = 0; i < json.length; i += 1) {
       // want purchase orders for this employee as sales rep
       // top thirty purchase orders by amount_total
       var detail = {
           filter: "salesrep_id = " + json[i].employee_id,
           order: "amount_total desc",
           pagesize: 30,
           offset: 0,
           verbose: false
       };
       var ordersAsSalesRep = getResource("purchaseorders", detail);
       json[i].ordersAsSalesRep = ordersAsSalesRep;
   }
}

In the following code snippet, include the results of a resource GET by amending the transaction summary:

// for a PUT (perhaps to update the name) of one or more employees
// add the picture into the result
if ("PUT" == req.verb && "employee" == req.resourceName) {
    var txsummary = json.txsummary;
    for (var i = 0, len = txsummary.length;  i < len;  i += 1) {
        var meta = txsummary[i]["@metadata"];
        if ("UPDATE" == meta.verb && "employee" == meta.resource) {
            var detail = { filter: "employee_id = " + summary[i].employee_id  };
            var picInfo = getResource("employee_picture", detail);
            if (picInfo && picInfo.length > 0) {
               txsummary[i].the_picture = picInfo[0].picture;
            }
        }
    }
}

Tip! You can combine these two examples and delete the usual transaction-summary, redirecting it to be the getResource result.

Advanced Usage

You have full control over the result and can do pretty much anything. The following is an example:
  1. Create a new JavaScript resource named MyResource defined as:
    return { Happy: ['New', 'Year']};
  2. In the REST Lab, view the result by performing a GET request, which is a different formatting of the previous JSON. Complete the following:
    1. Make sure you are at least functioning by defining a simple response event. If the response event appears to be non-functional, check that it is configured as a response event and not as a REQUEST event:
      // MUST be an object or an array, if not, it is coerced into one (and probably NOT what you want)
      if ('GET' == req.verb.name() && 'MyResource' == req.resourceName) {
          json = ["I got what I expected"];
      }
      else {
          // this is returned on ALL other requests, make sure you delete this !!!
          json = ["Not what I wanted"];
      }
    2. Change to a more specific handler without the else condition:
      // Note double equals, as you are comparing JavaScript strings with java.lang.String objects
      if ('GET' == req.verb.name() && 'MyResource' == req.resourceName) {
        json = getResource('demo:customer');
      }
      The handler takes a value from the request and creates a new customer.

More Information

For more information: