ratelimit module

The APIs in the ratelimit module allows you to define keys that represent rate thresholds, counters, and concurrent transactions.

To access the APIs in the ratelimit module, use the require('ratelimit') statement, such as var rl = require('ratelimit');.

How the DataPower® Gateway stores and manages the keys is based on the DataPower service and its configuration.
  • For the API Gateway, either the quota enforcement server or the GatewayScript rate limiting gateway peering instance is used. The quota enforcement server is a system wide configuration that is defined in the default domain.
    • When the GatewayScript rate limiting gateway peering instance is defined in the gateway peering manager, the gateway peering instance is used.
    • When the GatewayScript rate limiting gateway peering instance is not defined in the gateway peering manager, the quota enforcement server is used.
  • For all other DataPower services, the quota enforcement server is always used.

A rate threshold measures the maximum number of resources that are requested during an interval for the specific traffic type. The rate threshold is expressed in tokens per interval. The token represents the monitored resources. The bucket represents the resource pool that contains tokens. The bucket has a maximum capacity.

For each request, a defined number of tokens in the bucket can be requested. When available tokens in the bucket are enough for a request, the request is accepted and the requested tokens are used and removed from the bucket. Otherwise, the threshold is exceeded, and the next incoming requests are rejected.

Rate limiting supports the following types of rate thresholds. The difference between these threshold types is that the token bucket threshold is affected by the maximum capacity of the bucket.
Rate-based threshold
APIs for managing the rate-based threshold.
Token bucket threshold
APIs for managing the token bucket threshold.
Rate limiting supports flexible counting for any specific occurrences and counting for concurrent transactions that can be processed simultaneously.
Counter
APIs for managing the counter for specific occurrences.
Concurrent transactions
APIs for managing the counter for concurrent transactions.

APIs for the rate-based threshold

This section lists all APIs for managing the rate-based threshold.

rl.rateCreate()

Creates and initializes a rate object.

Syntax

rl.rateCreate(key, tokens, interval[, intervalType])
rl.rateCreate( {key:key, token:tokens, interval:interval[, intervalType:intervalType]} )
keyThe unique identifier that represents a defined threshold for the specific traffic type. The key can be any characters accessible in the GatewayScript file.
tokensThe maximum number of resources that can be requested during an interval, the rate-based threshold. This parameter also indicates the number of tokens that the bucket contains when the bucket is initialized. The bucket is initialized when this API is called. This parameter is an integer. The value is in the range 0 - (253 - 1).
intervalThe frequency between enforcements. This parameter is an integer. The unit is second. The value is in the range 1 - 31536000.
intervalTypeThe type of interval. This parameter is a string. This parameter value is fixed or rolling. The default value is fixed.

The rl.rateCreate() API creates and initializes a rate object that indicates the rate-based initial threshold associated with the specified key. When the rate object of the specified key exists, no new rate object is created and the rate object that was previously created by rl.rateCreate() API is returned. But the value of tokens, interval, and intervalType can be changed. The tokens of the number tokens refill the bucket for each new interval. Calling the rl.rateCreate() API multiple times does not impact the time when token refilling occurs.

When a request is received, whether the request can be accepted is based on the interval type. For example, call rl.rateCreate('192.168.1.1', 10, 10) to create a rate object. The bucket is initialized at 8:00:00, the interval is 10 seconds, and a request is received at 8:00:18.
  • The fixed interval is a discrete block of time, such as from 8:00:00 to 8:00:10, from 8:00:10 to 8:00:20, and so on. The request can be accepted when the threshold is not exceeded during the interval 8:00:10 to 8:00:20. When the interval type is fixed, you must check whether the threshold is exceeded from 8:00:10 to 8:00:18. If the threshold is exceeded, the request is rejected.
  • The rolling interval is a sliding time-window that is relative to the time when a request is received. The request can be accepted when the threshold is not exceeded during the previous 10 seconds, from 8:00:08 to 8:00:18. When the interval type is rolling, you must check whether the threshold is exceeded from 8:00:08 to 8:00:18. If the threshold is exceeded, the request is rejected.

For rate object, in each interval, immutable 10 tokens are available to use.

Example

Define a rate-based initial threshold of 10 tokens in 10 seconds. This threshold is associated with key 192.168.1.1.
var rl = require('ratelimit');
var rate = rl.rateCreate('192.168.1.1', 10, 10, 'fixed');

rate object

The rate object provides the following APIs to decrease, reset, and modify the token number.

All API specifications use the rate object that is assumed to be defined, for example, by the following statements.
var rl = require('ratelimit');
var rate = rl.rateCreate('192.168.1.1', 10, 10, 'fixed');

rate.remaining()

Returns the number of remaining tokens.

Syntax

rate.remaining(function(err, remaining, timeToReset))
functionThe asynchronous callback function that runs when the number of remaining tokens is obtained.
errThe error information if any error occurs during the processing.
remainingThe number of remaining tokens in the bucket.
timeToResetThe number of remaining seconds in the current interval.
The rate.remaining() API obtains the number of remaining tokens associated with the current key.

rate.remove()

Removes a specific number of tokens from the bucket.

Syntax

rate.remove(number, function(err, remaining, timeToReset))
numberThe number of tokens for a request to use. This defined number of tokens are removed when the request is accepted. This parameter is an integer. The value is in the range 0 - (253 - 1).
functionThe asynchronous callback function that runs when a specific number of tokens are removed.
errThe error information if any error occurs during the processing.
remainingThe number of remaining tokens in the bucket.
timeToResetThe number of remaining seconds in the current interval.
When the request is accepted, the rate.remove() API removes the defined number of tokens associated with the current key. After the token removal, if the remaining value is less than the number value, the remaining tokens in the bucket are not enough for the next request. When the next request comes, the threshold is exceeded and the request is rejected. In this situation, no tokens are removed from the bucket and the number of remaining tokens does not change.
Example
The rate-based initial threshold is 10 tokens per 10 seconds. In the first interval, when the first request comes at the third second, 6 tokens are removed and the number of remaining tokens is 4. Because 4 is less than 6, the remaining tokens are not enough for the next request. When the next request comes, the threshold is exceeded and the request is rejected. The number of remaining tokens keeps the value of 4.
var rl = require('ratelimit');
var rate = rl.rateCreate('192.168.1.1', 10, 10);
rate.remove(6, function(err, remaining, timeToReset){
  if(err) { 
    console.error('exceeded ratelimit');
    session.reject('Ratelimit exceeded');
  }
  else {
      console.info('ratelimit check ok, remaining token:' + remaining);
  }
});

rate.reset()

Resets the number of tokens that can be requested to the initial threshold.

Syntax

rate.reset(function(err, remaining, timeToReset))
functionThe asynchronous callback function that runs when reset is implemented.
errThe error information if any error occurs during the processing.
remainingThe number of remaining tokens in the bucket.
timeToResetThe number of remaining seconds in the current interval.
The rate.reset() API resets the number of tokens associated with the current key to the initial threshold that the rl.rateCreate() API defines; and this API starts a new interval. The reset threshold takes effect in the new interval immediately after the rate.reset() API is called.
Example
Reset the number of tokens associated with the key 192.168.1.1 to the initial threshold.
var rl = require('ratelimit');
//Retrieve rate threshold associated with key '192.168.1.1'
var rate = rl.rateCreate('192.168.1.1'); 
if(rate){
  rate.reset(function(err, remaining, timeToReset) {
    if (err) {
      console.error('Error:' + err);
      // error handling actions
    }
    else {
      console.info('Reset ratelimit');
    }
  });
}

rate.set()

Assigns a new value to the number of tokens that can be requested.

Syntax

rate.set(number, function(err, remaining, timeToReset))
numberThe new value that is assigned to the token number. This parameter is an integer. The value is in the range 0 - (253 - 1).
functionThe asynchronous callback function that runs when the new value is assigned to the token number.
errThe error information if any error occurs during the processing.
remainingThe number of remaining tokens in the bucket.
timeToResetThe number of remaining seconds in the current interval.
The rate.set() API sets the new value to the number of tokens associated with the current key; and this API starts a new interval. The new value must be less than or equal to the initial threshold that the rl.rateCreate() API defined. If the new value is greater than the initial threshold, the error occurs. The new value takes effect in the new interval immediately after the rate.set() API is called.
Example
Set the token number as 7.
var rl = require('ratelimit');
var rate = rl.rateCreate('192.168.1.1', 10, 10);
var number = 7;
rate.set(number, function(err, remaining, timeToReset){
  if(err) {
    console.error('exceeded ratelimit');
    session.reject('Ratelimit exceeded');
  }
  else {
    console.info('Set ratelimit');
  }
});

APIs for the token bucket threshold

This section lists all APIs for managing the token bucket threshold.

rl.tokenbucketCreate()

Creates and initializes a tokenbucket object.

Syntax

rl.tokenbucketCreate(key, maxTokens, tokens, interval[, intervalType])
rl.tokenbucketCreate( {key:key, maxTokens:maxTokens, tokens:tokens, interval:interval[, intervalType:intervalType]} )
keyThe unique identifier that represents a defined threshold for the specific traffic type. The key can be any characters accessible in the GatewayScript file.
maxTokensThe maximum capacity of the bucket. This parameter is an integer. The value is in the range 0 - (253 - 1). For token bucket, the remaining tokens in previous interval are kept in the bucket so that they can be used in next interval. maxTokens is used to make sure that the bucket maximum capacity cannot be exceeded anytime. When the token number is larger than maxTokens, maxTokens becomes the number of available tokens in the bucket.
tokensThe maximum number of resources that can be requested during an interval, the token bucket threshold. This parameter also indicates the number of tokens that the bucket contains when the bucket is initialized. The bucket is initialized when this API is called. This parameter is an integer. The value is in the range 0 - (253 - 1).
intervalThe frequency between enforcements. This parameter is an integer. The unit is second. The value is in the range 1 - 31536000.
intervalTypeThe type of interval. This parameter is a string. This parameter value is fixed or rolling. The default value is fixed.

The rl.tokenbucketCreate() API creates and initializes a tokenbucket object that indicates the token bucket initial threshold associated with the specified key. When the tokenbucket object of the specified key exists, no new tokenbucket object is created and the tokenbucket object that was previously created by rl.tokenbucketCreate() API is returned. But the value of tokens, maxTokens, interval, and intervalType can be changed. The tokens of the number tokens refill the bucket for each new interval. Calling the rl.tokenbucketCreate() API multiple times does not impact the time when token refilling occurs.

When a request is received, whether the request can be accepted is based on the interval type. For example, call rl.tokenbucketCreate('192.168.1.1', 15, 10, 10) to create a tokenbucket object. The bucket is initialized at 8:00:00 and a request is received at 8:00:18. For each request, one token is used.
  • The fixed interval is a discrete block of time, such as from 8:00:00 to 8:00:10, from 8:00:10 to 8:00:20, from 8:00:20 to 8:00:30, and so on. The request can be accepted when the threshold is not exceeded during the interval 8:00:10 to 8:00:20. When the interval type is fixed, you must check whether the threshold is exceeded from 8:00:10 to 8:00:18. If the threshold is exceeded, the request is rejected.

    Assume that two tokens are not used during 8:00:10 to 8:00:20. These two tokens are propagated to the next interval that is from 8:00:20 to 8:00:30. Because 10 tokens refill the bucket for each new interval, total 12 tokens are available to use from 8:00:20 to 8:00:30. However, for rate object, in each interval, immutable 10 tokens are available to use. Compared with rate object, it is possible to process 12 requests in one interval for tokenbucket object.

  • The rolling interval is a sliding time-window that is relative to the time when a request is received. The request can be accepted when the threshold is not exceeded during the previous 10 seconds, from 8:00:08 to 8:00:18. When the interval type is rolling, you must check whether the threshold is exceeded from 8:00:08 to 8:00:18. If the threshold is exceeded, the request is rejected.

Example

Create the token bucket initial threshold. The threshold is associated with key 192.168.1.1.
var rl = require('ratelimit');
var tokenbucket = rl.tokenbucketCreate('192.168.1.1', 15, 10, 10,'fixed');

tokenbucket object

The tokenbucket object provides the following APIs to decrease, reset, and modify the token number.

All API specifications use the tokenbucket object that is assumed to be defined, for example, by the following statements.
var rl = require('ratelimit');
var tokenbucket = rl.tokenbucketCreate('192.168.1.1', 15, 10, 10,'fixed');

tokenbucket.remaining()

Returns the number of remaining tokens.

Syntax

tokenbucket.remaining(function(err, remaining, timeToReset))
functionThe asynchronous callback function that runs when the number of remaining tokens is obtained.
errThe error information if any error occurs during the processing.
remainingThe number of remaining tokens in the bucket.
timeToResetThe number of remaining seconds in the current interval.
The tokenbucket.remaining() API obtains the number of remaining tokens associated with the current key.

tokenbucket.remove()

Removes a specific number of tokens from the bucket.

Syntax

tokenbucket.remove(number, function(err, remaining, timeToReset))
numberThe number of tokens for a request to use. This defined number of tokens are removed when the request is accepted. This parameter is an integer. The value is in the range 0 - (253 - 1).
functionThe asynchronous callback function that runs when a specific number of tokens are removed.
errThe error information if any error occurs during the processing.
remainingThe number of remaining tokens in the bucket.
timeToResetThe number of remaining seconds in the current interval.
When the request is accepted, the rate.remove() API removes the defined number of tokens associated with the current key. After the token removal, if the remaining value is less than the number value, the remaining tokens in the bucket are not enough for the next request. When the next request comes, the threshold is exceeded and the request is rejected. In this situation, no tokens are removed from the bucket and the number of remaining tokens does not change.
Example
In the first interval, when the first request comes at the third second, 6 tokens are removed and the number of remaining tokens is 4. Because 4 is less than 6, the remaining tokens are not enough for the next request. When the next request comes, the threshold is exceeded and the request is rejected. The number of remaining tokens keeps the value of 4.
var rl = require('ratelimit');
var tokenbucket = rl.tokenbucketCreate('192.168.1.1', 15, 10, 10);
tokenbucket.remove(6, function(err, remaining, timeToReset){
  if(err){
    console.error('exceeded ratelimit');
    session.reject('Ratelimit exceeded');
  }
  else {
    console.info('ratelimit check ok, remaining token:' + remaining);
  }
});

tokenbucket.reset()

Resets the number of tokens that can be requested to the initial threshold.

Syntax

tokenbucket.reset(function(err, remaining, timeToReset))
functionThe asynchronous callback function that runs when reset is implemented.
errThe error information if any error occurs during the processing.
remainingThe number of remaining tokens in the bucket.
timeToResetThe number of remaining seconds in the current interval.
The tokenbucket.reset() API resets the number of tokens associated with the current key to the initial threshold that the rl.tokenbucketCreate() API defined; and this API starts a new interval. The reset threshold takes effect in the new interval immediately after the tokenbucket.reset() API is called.
Example
Reset the number of tokens associated with the key 192.168.1.1 to the initial threshold.
var rl = require('ratelimit');
//Retrieve rate threshold associated with key '192.168.1.1'
var tokenbucket = rl.tokenbucketCreate('192.168.1.1'); 
if(tokenbucket){
  tokenbucket.reset(function(err, remaining, timeToReset) {
    if (err) {
      console.error('Error:' + err);
      // error handling actions
    }
    else {
      console.info('Reset ratelimit');
    }
  });
}

tokenbucket.set()

Assigns a new value to the number of tokens that can be requested.

Syntax

tokenbucket.set(number, function(err, remaining, timeToReset))
numberThe new value that is assigned to the token number. This parameter is an integer. The value is in the range 0 - (253 - 1).
functionThe asynchronous callback function that runs when the new value is assigned to the token number.
errThe error information if any error occurs during the processing.
remainingThe number of remaining tokens in the bucket.
timeToResetThe number of remaining seconds in the current interval.
The tokenbucket.set() API sets the new value to the number of tokens associated with the current key; and this API starts a new interval. The new value must be less than or equal to the initial threshold that the rl.tokenbucketCreate() API defined. If the new value is greater than the initial threshold, the error occurs. The new value takes effect in the new interval immediately after the tokenbucket.set() API is called.
Example
Set the token number as 7.
var rl = require('ratelimit');
var tokenbucket = rl.tokenbucketCreate('192.168.1.1', 15, 10, 10);
var number = 7;
tokenbucket.set(number, function(err, remaining, timeToReset){
  if(err) {
    console.error('exceeded ratelimit');
    session.reject('Ratelimit exceeded');
  }
  else {
    console.info('Set ratelimit');
  }
});

APIs for the counter

This section lists all APIs for managing the counter for specific occurrences.

count object

The count object provides the following APIs to modify the value of a counter for the current key.

All API specifications use the count object that is assumed to be defined, for example, by the following statements.
var rl = require('ratelimit');
var count = rl.countCreate('192.168.1.1', 15);

count.add()

Increases the value of a counter.

Syntax

count.add(number, function(err, count))
numberThe specific number to add to the counter. This parameter is an integer. The value is in the range 0 - (253 - 1).
functionThe asynchronous callback function that runs when the counter is added.
errThe error information if any error occurs during the processing.
countThe current value of a counter.
The count.add() API increases the value of the counter associated with the current key by a certain number.
Example
Add the value of a counter by one.
var hm = require('header-metadata'),
    sm = require('service-metadata'),
    rl = require('ratelimit');
var key = hm.current.get('Host');
//Define the initial value of the counter as 10
var initialValue = 10;
var counter = rl.countCreate(key, initialValue);
counter.add(1, function(err, count){
  if (err) {
    console.error('Error:' + err);
    //Error handling
  }
  else {
    console.info('Add one token to counter successfully');
  }
});

count.count()

Returns the value of a counter.

Syntax

count.count(function(err, count))
functionThe asynchronous callback function that runs when the value of counter is obtained.
errThe error information if any error occurs during the processing.
countThe current value of a counter.
The count.count() API obtains the value of the counter associated with the current key.

count.reset()

Resets the value of a counter to the initial value.

Syntax

count.reset(function(err))
functionThe asynchronous callback function that runs when reset is implemented.
errThe error information if any error occurs during the processing.
The count.reset() API resets the the value of the counter associated with the current key to the initial value that the rl.countCreate() API defined. If the initial value is not provided, the counter value is reset to zero. The reset value takes effect immediately after the count.reset() API is called.
Example
Reset the value of the counter associated with the key 192.168.1.1 to the initial value.
var rl = require('ratelimit');
var counter = rl.countCreate('192.168.1.1');
if(counter){
  counter.reset(function(err) {
    if (err) {
      console.error('Error:' + err);
    }
    else {
      console.info('Reset the counter');
    }
  });
}

count.set()

Assigns a new value to the value of a counter.

Syntax

count.set(number, function(err))
numberThe new value that is assigned to the counter. This parameter is an integer. The value is in the range 0 - (253 - 1).
functionThe asynchronous callback function that runs when the new value is assigned to the counter.
errThe error information if any error occurs during the processing.
The count.set() API assigns a new value to the value of the counter associated with the current key. The new value takes effect immediately after the count.set() API is called.
Example
Set the value of the counter associated with the key 192.168.1.1 to 100.
var rl = require('ratelimit');
var counter = rl.countCreate('192.168.1.1');
var number = 100;
counter.set(number, function(err){
  if(err) {
    console.error('Error:' + err);
    session.reject('exceeded limit');
  }
  else {
    console.info('Count is set');
  }
});

count.sub()

Subtracts the value of a counter.

Syntax

count.sub(number, function(err, count))
numberThe specific number to subtract from the counter. This parameter is an integer. The value is in the range 0 - (253 - 1).
functionThe asynchronous callback function that runs when the counter is subtracted.
errThe error information if any error occurs during the processing.
countThe current value of a counter. The value can be negative.
The count.sub() API subtracts the value of the counter associated with the current key by a certain number.
Example
Subtract the value of a counter by one.
var hm = require('header-metadata'),
    sm = require('service-metadata'),
    rl = require('ratelimit');
var key = hm.current.get('Host');
//Define the initial value of the counter as 10
var initialValue = 10;
var counter = rl.countCreate(key, initialValue);
counter.sub(1, function(err, count){
  if (err) {
    console.error('Error:' + err);
    //Error handling
  }
  else {
    console.info('Subtract one token from counter');
  }
});

rl.countCreate()

Creates and initializes a count object.

Syntax

rl.countCreate(key[, initialValue])
rl.countCreate( {key:key[, initialValue:initialValue]} )
keyThe unique identifier that represents a counter. The key identifies the traffic type. The key can be any characters accessible in the GatewayScript file.
initialValueThe initial value of a counter. This parameter is an integer. The value is in the range 0 - (253 - 1). The default value is zero.
The rl.countCreate() API creates a counter for counting the number of any specific occurrences. The counter is associated with the specified key.

Example

Define the initial value of a counter as 15. This counter is associated with key 192.168.1.1.
var rl = require('ratelimit');
var count = rl.countCreate('192.168.1.1', 15);

APIs for concurrent transactions

This section lists all APIs for managing the counter for concurrent transactions.

concurrentTransaction object

The concurrentTransaction object provides the following APIs to count the number of concurrent transactions for the current key.

All API specifications use the concurrentTransaction object that is assumed to be defined, for example, by the following statements.
var rl = require('ratelimit');
var concurrentTransaction = rl.concurrentCreate('192.168.1.2');

concurrentTransaction.add()

Increases the counter that counts the number of concurrent transactions first and then decreases the counter automatically when the transaction ends.

Syntax

concurrentTransaction.add(number, function(err, count))
numberThe specific number that is added to the counter for concurrent transactions. This parameter is an integer. The value is in the range 0 - (253 - 1).
functionThe asynchronous callback function that runs when the processing is finished.
errThe error information if any error occurs during the processing.
countThe current counter for concurrent transactions.
The concurrentTransaction.add() API first increases the counter that counts the number of concurrent transactions that is associated with the current key by the specified number. When the transaction ends, the counter is decreased automatically by the number of previous total increments. This means that the counter returns to the original value before calling the API.

For example, in a processing rule, on the first GatewayScript action, the concurrentTransaction.add(10, function) API is called and on the second GatewayScript action, the concurrentTransaction.add(5, function) API is called. The concurrentTransaction objects that are called on both GatewayScript actions must have the same key. When the transaction ends, the counter is automatically decreased by the total increments, 15.


concurrentTransaction.count()

Returns the number of the current concurrent transactions.

Syntax

concurrentTransaction.count(function(err, count))
functionThe asynchronous callback function that runs when the processing is finished.
errThe error information if any error occurs during the processing.
countThe current counter for concurrent transactions.
The concurrentTransaction.count() API obtains the number of the current concurrent transactions with the current key.

concurrentTransaction.end()

Decreases the number of concurrent transactions before the transaction ends.

Syntax

concurrentTransaction.end(function(err, count))
functionThe asynchronous callback function that runs when the processing is finished.
errThe error information if any error occurs during the processing.
countThe current counter for concurrent transactions.
After the concurrentTransaction.add() API is called, the counter that counts concurrent transactions is increased. Before the transaction ends, when you want to decrease the counter, call the concurrentTransaction.end() API. The concurrentTransaction.end() API can immediately decrease the counter that is associated with the current key by the number of previous total increments.

For example, in a processing rule, on the first GatewayScript action, the concurrentTransaction.add(10, fn) API is called and on the second GatewayScript action, the concurrentTransaction.add(5, fn) API is called. On the third GatewayScript action, when the concurrentTransaction.end(fn) API is called, the counter is immediately decreased by the total increments, 15. The prerequisite is that the concurrentTransaction objects that are called on all GatewayScript actions must have the same key.


rl.concurrentCreate()

Creates and initializes a concurrenctTransaction object.

Syntax

rl.concurrentCreate(key)
rl.concurrentCreate( {key:key} )
keyThe unique identifier that represents a concurrentTransaction object. The key identifies the traffic type. The key can be any characters accessible in the GatewayScript file.
The rl.concurrentCreate() API creates and initializes a concurrentTransaction object that is associated with the specified key. The concurrentTransaction object is a special counter that counts the number of concurrent transactions.

Example

Create and initialize the concurrentTransaction object that is associated with key 192.168.1.2.
var rl = require('ratelimit');
var concurrentTransaction = rl.concurrentCreate('192.168.1.2');