Skip to content
This repository has been archived by the owner on Jul 14, 2022. It is now read-only.

Helper functions

wwitman edited this page Feb 16, 2015 · 4 revisions

Understanding helper functions

Helper functions let you programmatically set certain option values for the a127 cache, quota, spike arrest, and oauth policies.

What are helper functions used for?

Use helper functions to programmatically set certain values for Apigee-127 policies. Helper functions are referenced by individual policies and are called whenever the policy is invoked.

For example, you can configure a helper function to set a cache key programmatically. If you attach that cache policy to an API endpoint, the helper function is called whenever that endpoint is invoked. This pattern allows you to configure caches based on context, such as the client IP or the value of a query parameter.

When are helper functions called?

Helper functions are called whenever a request is received, and before any controller code executes.

What can I set with helper functions?

You can set the following policy parameter values with helper functions:

  • Cache policy

    • key -- Sets the cache key.
  • Spike arrest policy

    • key -- Specifies a distinct spike arrest counter or "bucket". If not set, a single count is maintained for all API traffic.
  • Quota policy

    • key -- Specifies a distinct quota "bucket". Each bucket maintains a separate counter value from other counters. If not set, a single quota count is maintained for all APIs.
  • OAuth 2.0 policy

    • passwordCheck -- Specifies a function that validates the password for the password grant type.

How to configure a helper function

Let's look at how to configure a helper function to set a cache key for the cache policy.

To set up a cache, you first declare a cache provider in your swagger.yaml file with the x-a127-services extension:

  x-a127-services
    mycache:     
      provider: volos-cache-memory
      options:
        name: hello-cache
        ttl: 60000 

Then, here's the pattern for applying the cache to a path using the x-a127-apply extension:

      paths:
          /hello_cached:
              x-swagger-router-controller: hello_world
              x-a127-apply:
                mycache: 
                  key:
                    helper: volos
                    function: cacheKey
              get:
                ...

The key property specifies a helper function that programmatically sets the cache key whenever this API path is invoked.

In this example, the helper function is called cacheKey, and it is defined in the ./api/helpers/volos.js. file.

Sample helper implementation

Continuing with the cache example, here's a simple cacheKey helper function implementation. It sets a cache key value passed in a query parameter.

This approach is useful where you want to selectively cache data. For example, you might want to cache data returned from an /addresses endpoint based on the name of a user or a business name, or something similar. For example: /addresses?name=Wallgreens

      'use strict';

      module.exports = {
        cacheKey: cacheKey,
      };

      function cacheKey(req) {
      // This can check for a specific query parameter ("name" in this case)
        var key = req.swagger.params.name.value;
        return key;
      }

By default, helper files must be located in the ./api/helpers directory of your Apigee-127 project.

Programmatic access to request information

Here's a quick summary of patterns you can use to set request-specific values in helper functions:

  • Leveraging query parameters
  • Leveraging the request object
  • Leveraging the user ID
  • Leveraging the Client ID
  • Leveraging Volos management APIs

Leveraging query parameters

In the previous example, we obtained the value of a query parameter in a helper function, and used that value to set a cache key. We used the req.swagger object to obtain access to the query parameters.

Note: The req.swagger object is populated by the swagger-tools middleware component of Apigee-127. To read more about this object, see the Swagger tools middleware documentation.

Leveraging the request object

In this example, we leverage the request object to obtain the client IP address:

    function clientIp(req) {
      var key = req.connection.remoteAddress;
      console.log('clientIp Key: '+key);
      return key;
    }

You can obtain other useful information from the request object. You may be able to leverage some of this information in a helper. For example, to illustrate some possible information you can grab from the request, the following code in a helper function...

      util = require('util');
      ...
      var headers = req.headers;
      console.log("HEADERS: " + util.inspect(headers));

      var url = req.url;
      console.log("URL: " + util.inspect(url));

      var query = req.query;
      console.log("QUERY: " + util.inspect(query));


      var token = req.token;
      console.log("TOKEN: " + util.inspect(token));
      ...

...produces output like this when the API is called:

    HEADERS: { 'user-agent': 'curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8z zlib/1.2.5',
      host: 'localhost:10010',
      accept: '*/*',
      authorization: 'Bearer xiW7pJP8Ao2Lae9tVmLOW9z7' }

    URL: '/hello?name=Will&client_id=3ild49uslziJQKID9i3ld'

    QUERY: { name: 'Will', client_id: '3ild49uslziJQKID9i3ld' }

    TOKEN: { developerId: 'wwitman@@@GRh96DZw3hY6M4',
      appName: 'AppNoResources',
      appId: '3de7e05-58ed-4255-b095-f07fdce125',
      attributes: '',
      expires_in: '596253',
      scope: '' }

You can potentially use this information in a helper to set request-specific values. For example, you could extract custom headers and use them in your helper functions.

Leveraging the user ID

It's common to use a value like User ID (the ID of the user who is calling your API) to set cache, quota or other request-specific keys. Apigee-127 does not necessarily store or pass user user-specific information around. Assuming that a client app has the user ID (the user is required to log in), you could pass the user ID in a request as a query parameter or in a header, and extract the value as described previously.

Leveraging the client ID

If you're using OAuth security, you may wish to set a cache key based on the client ID that the client app received when it was registered with the authorization server.

The client ID is a public value and can be provided readily by the client app in a query parameter on each API call. Then, just like we've seen in previous examples, your helper code could extract the value of a client_id query parameter and use it to set the cache, quota, or other key. For example, in your helper code, do:

    var client_id = req.swagger.params.client_id.value;

Leveraging Volos management APIs

If you want to obtain the client ID programmatically in a helper, you could use the volos-management-apigee module to retrieve the developer app, and from that object, obtain the client ID. Something like this:

    var management = a127.resource('management');
    ... 
    management.getDeveloperApp(dev, appname, function(err, app) {
        if (err) { console.log("ERRORR") } else {

      console.log("ID: " + app.credentials[0].key);
       }
      });

To access a127.resource('management'), a volos-management-* module must be declared in your Swagger file. For example:

    management:
      provider: volos-management-apigee
      options:
        organization: *organization
        user: *username
        password: *password

For detailed information on the Volos management APIs, see the apigee-127/volos/management/commmon README on GitHub.

For an example showing how the volos-management-* module is employed in an a127 project, see the weather-advanced sample on GitHub.

More about programmatic access to Apigee-127 services

To learn about techniques for programmatically accessing Apigee-127 services in controller functions, see this blog:

And, see the a127-samples repo on GitHub for examples demonstrating programmatic access to quotas, caches, and more.

More examples

Several examples in the a127-samples repository on GitHub use helper functions. See for example:

See also these blog posts:

Clone this wiki locally