Install Gateway

Requirements

Tree Gateway uses a Redis database to store it's configurations and to manage all nodes of it's cluster.

So, if you don't have a redis database already running, install it before going further.

For docker users, the easiest way to have a simple standalone redis is just running the following command:

$ docker run -p 6379:6379 -d --name redis redis:3.0.7-alpine

Installation

$ npm install tree-gateway -g

After this, you can run the gateway using the following command:

$ treeGateway

Or, for docker users:

$ docker run --name tree-gateway -p 8000:8000 --link redis:redis -d treegateway/tree-gateway:latest

Now, you can go to Configuration step.

Gateway Configuration

When tree-gateway starts, it uses the tree-gateway Config File to load the initial configuration needed.

When start the gateway, you can inform the location of this config file:

$ treeGateway -c ./tree-gateway.yaml

If you do not inform any file, the gateway will try to find one with the name tree-gateway.json or tree-gateway.yaml located in the directory where you start the gateway. If no config file exists, the gateway will start with its default configurations and will save a file ./tree-gateway.yaml that will contains these configurations.

The most important information in this configuration file is the Database location. After this first step, the gateway can ask the database for all the other configurations, such as:

  • the gateway itself - which kind os services are enabled / monitors / protocols and ports for the listening services / loggers etc;
  • the admin users - Who can access the configuration services;
  • the installed middlewares - To extend gateway features / listen and handle events etc;
  • and all API configurations - The main purpose of the gateway: to route, secure and manage your APIs.

So, all of those configurations are inserted directly into the config database. If you change a configuration (regardless of which is), messages are sent to all cluster nodes to inform the new values. This happens without any need for a gateway restart (we can call it a hot-configuration-deploy). We provide 3 different ways to you manage all of those configurations:

In order to interact with the Gateway REST Api you must also create a first user/password.

To create this fisrt user, you must use the CLI tool (treeGatewayConfig).

tree-gateway Config File

This is the Server config descriptor. It support the following properties:

Property Type Description Required
database DatabaseConfig Configurations for gateway databases. true
gateway GatewayConfig The default gateway configuration. false
middlewarePath string Folder where the gateway will install its middleware functions. false
rootPath string The root folder where the gateway will use as its work dir. false

DatabaseConfig

Configure gateway database.

Property Type Description Required
redis RedisConfig Configurations for gateway REDIS database. true

The configuration file can be written in json or yaml formats.

Example:

{
    "rootPath": ".",
    "database": {
        "redis": {
            "standalone": {
                "host": "{REDIS_PORT_6379_TCP_ADDR}",
                "port": "{REDIS_PORT_6379_TCP_PORT}"
            }
        }
    }
}

or

rootPath: '.'
database:
    redis:
        standalone:
            host: '{REDIS_PORT_6379_TCP_ADDR}'
            port: '{REDIS_PORT_6379_TCP_PORT}'

RedisConfig

This will configure how the gateway will connect to the Redis database. It is a required configuration in tree-gateway Config File and supports the following properties:

Property Type Description Required
standalone RedisNodeConfig Configure the connection to a standalone Redis. false
sentinel RedisSentinelConfig Configure the connection to Redis using sentinels. false
cluster RedisNodeConfig[] Configure the connection to a redis cluster. false
options RedisOptionsConfig Configure additional options to be passed to redis driver. false

It is important to observe that none of those properties are required, however, you need to specify one (and no more than one) option between standalone, sentinel and cluster.

RedisNodeConfig

Configure a redis node where the gateway will connect.

It support the following properties:

Property Type Description Required
host string The hostname of the redis node. true
port string or number The port of the redis node. false
password string The password to connect on the redis node. false

If none of these are provided, the port 6379 will be used as default.

Example:

 "database": {
    "redis": {
        "standalone": {
            "host": "localhost",
            "port": 6379
        }
    }
}

or

database:
  redis:
    standalone:
      host: "localhost"
      port: 6379

You can write the values for these properties between { and }, to inform to the gateway that an environment variable should be used:

 "database": {
    "redis": {
        "standalone": {
            "host": "{redis_hostname}",
            "port": "{redis_port}"
        }
    }
}

or

database:
  redis:
    standalone:
      host: "{redis_hostname}"
      port: "{redis_port}"

In this example above, the gateway will use an environment variable called redis_hostname to find out the name of the redis host and redis_port as the redis connection port.

RedisSentinelConfig

Configure a redis using sentinels.

It support the following properties:

Property Type Description Required
name string Group os instances to connect (master/slaves group). true
nodes RedisNodeConfig[] List of sentinel nodes. true

Example:

{
    "database": {
        "redis": {
            "sentinel": {
                "name": "redis1",
                "nodes": [
                {
                    "host": "localhost",
                    "port": 6379
                }
                ]
            }
        }
    }
}

or

database:
  redis: 
    sentinel:
      name: redis1
      nodes:
      - host: localhost
        port: 6379

Redis Cluster

Configure a list of start nodes for a redis cluster. You don't need to provide all cluster nodes. The gateway will use this start list and discover the cluster automatically.

Example:

{
    "database": {
        "redis": {
            "cluster": [
                {
                    "host": "host1",
                    "port": 6379
                },
                {
                    "host": "host2",
                    "port": 6379
                }
            ]
        }
    }
}

or

database:
  redis: 
    cluster:
    - host: host1
      port: 6379
    - host: host2
      port: 6379

RedisOptionsConfig

Configure additional options to be passed to redis driver.

It support the following properties:

Property Type Description Required
password string Fallback password. Used when not defined in a node. false
keyPrefix string Prefix to be appended to all keys (defaults to ''). false
connectionName string Connection name, for monitoring purposes. false
db number Database index. false

Example:

{
    "rootPath": ".",
    "database": {
        "redis": {
            "standalone": {
                "host": "{REDIS_PORT_6379_TCP_ADDR}",
                "port": "{REDIS_PORT_6379_TCP_PORT}"
            }, 
            "options": {
                "db": 1
            }
        }
    }
}

or

rootPath: "."
database:
  redis: 
    standalone:
      host: "{REDIS_PORT_6379_TCP_ADDR}"
      port: "{REDIS_PORT_6379_TCP_PORT}"
    options:
      db: 1

ProtocolConfig

Configure a protocol to be used by Tree-Gateway or by the Gateway Admin API.

It supports the following properties:

Property Type Description Required
http HttpConfig Configure the HTTP protocol. false
https HttpConfigs Configure the HTTPS protocol. false

HttpConfig

Configurations for HTTP listener. It supports the following properties:

Property Type Description Required
listenPort number The listen port. true

HttpsConfig

Configurations for HTTPS listener. It supports the following properties:

Property Type Description Required
listenPort number The listen port. true
privateKey string Path to the private key file. true
certificate string Path to the certificate file. true

Example:

{
    "protocol": {
        "http": {
            "listenPort": 8000
        },
        "https": {
            "listenPort": 8001,
            "privateKey": "./server.key",
            "certificate": "./server.crt"                        
        }
    }
}

or

protocol:
  http:
    listenPort: 8000
  https:
    listenPort: 8001
    privateKey: "./server.key"
    certificate: "./server.crt"

MonitorConfig

Describes a Monitor configuration. It can be configured inside GatewayConfig.

A Monitor is an scheduled agent that can collect some kind of stats data periodically. Tree Gateway delivery two embeded Monitors: CpuMonitor and MemMonitor.

MonitorConfig support the following properties:

Property Type Description Required
name string name of the monitor. Can be cpu or mem true
statsConfig StatsConfig Configuration for stats collection true

Example:

{
    "monitor": [
        {
            "name": "cpu",
            "statsConfig": {
                "granularity": {
                    "duration": "1 minute",
                    "ttl": "2 days"
                }
            }
        }, 
        {
            "name": "mem",
            "statsConfig": {
                "granularity": {
                    "duration": "1 minute",
                    "ttl": "2 days"
                }
            }            
        }
    ]
}

or

monitor:
- name: cpu
  statsConfig:
    granularity:
      duration: 1 minute
      ttl: 2 days
- name: mem
  statsConfig:
    granularity:
      duration: 1 minute
      ttl: 2 days

LoggerConfig

Describes the configuration for the Log system.

It support the following properties:

Property Type Description Required
level 'error', 'info' or 'debug' Configure the minimum log level. false
console LogConsoleConfig Configure a Console reporter for the log system. false
file LogFileConfig Configure a File reporter for the log system. false

LogConsoleConfig

Configurations for the Console reporter of the Gateway Log system.

It support the following properties:

Property Type Description Required
level 'error', 'info' or 'debug' Configure the minimum log level for this reporter. false
timestamp boolean Flag indicating if we should prepend output with timestamps (default true). false
silent boolean Flag indicating whether to suppress output. false
colorize boolean Flag indicating if we should colorize output. false
json boolean Flag indicating if messages should be logged as JSON (default true). false
stringify boolean Flag indiciating if the output should be passed through JSON.stringify, resulting in single-line output. Most useful when used in conjunction with the json flag. (default false). false
prettyPrint boolean If true, additional JSON metadata objects that are added to logging string messages will be displayed as a JSON string representation. false
depth number Numeric indicating how many times to recurse while formatting the object with util.inspect (only used with prettyPrint: true) (default null, unlimited). false
humanReadableUnhandledException boolean Flag indicating if uncaught exception should be output as human readable, instead of a single line. false
showLevel boolean Flag indicating if we should prepend output with level (default true). false
stderrLevels string[] Array of strings containing the levels to log to stderr instead of stdout, for example ['error', 'debug', 'info']. (default ['error', 'debug']). false

LogFileConfig

Configurations for the File reporter of the Gateway Log system.

It support the following properties:

Property Type Description Required
level 'error', 'info' or 'debug' Configure the minimum log level for this reporter. false
outputDir string The directory name where the log files will be saved. false
timestamp boolean Flag indicating if we should prepend output with timestamps (default true). false
silent boolean Flag indicating whether to suppress output. false
colorize boolean Flag indicating if we should colorize output. false
json boolean Flag indicating if messages should be logged as JSON (default true). false
stringify boolean Flag indiciating if the output should be passed through JSON.stringify, resulting in single-line output. Most useful when used in conjunction with the json flag. (default false). false
prettyPrint boolean If true, additional JSON metadata objects that are added to logging string messages will be displayed as a JSON string representation. false
depth number Numeric indicating how many times to recurse while formatting the object with util.inspect (only used with prettyPrint: true) (default null, unlimited). false
humanReadableUnhandledException boolean Flag indicating if uncaught exception should be output as human readable, instead of a single line. false
showLevel boolean Flag indicating if we should prepend output with level (default true). false
stderrLevels string[] Array of strings containing the levels to log to stderr instead of stdout, for example ['error', 'debug', 'info']. (default ['error', 'debug']). false
maxsize number Max size in bytes of the log file, if the size is exceeded then a new file is created, a counter will become a suffix of the log file. false
maxFiles number Limit the number of files created when the size of the log file is exceeded. false
eol string String indicating the end-of-line characters to use (default to \n). false
logstash boolean If true, messages will be logged as JSON and formatted for logstash (default false). false
tailable boolean If true, log files will be rolled based on maxsize and maxfiles, but in ascending order. The filename will always have the most recent log lines. The larger the appended number, the older the log file. This option requires maxFiles to be set, or it will be ignored. false
maxRetries number The number of stream creation retry attempts before entering a failed state. In a failed state the transport stays active but performs a NOOP on it's log function. (default 2). false
zippedArchive boolean If true, all log files but the current one will be zipped. false

Example:

{
    "logger": {
        "level": "info",
        "console": {
            "level": "error",
            "colorize": true
        },
        "file": {
            "timestamp": true,
            "outputDir": "./logs",
            "json": false, 
            "prettyPrint": true 
        }
    }
}

or

logger:
  level: info
  console:
    level: error
    colorize: true
  file:
    timestamp: true
    outputDir: "./logs"
    json: false
    prettyPrint: true

AccessLoggerConfig

Describes the configuration for the AccessLog system. This log system logs only accesses (each request to the gateway server).

It support the following properties:

Property Type Description Required
msg string customize the default logging message. You can access any express property in request or response. false
expressFormat string Use the default Express/morgan request formatting. Enabling this will override any msg if true. Will only output colors when colorize set to true. false
console LogConsoleConfig Configure a Console reporter for the log system. false
file LogFileConfig Configure a File reporter for the log system. false

Example:

{
    "accessLogger": {
        "msg": "HTTP {{req.method}} - {{res.statusCode}} - {{req.url}} ({{res.responseTime}}ms) ",
        "console": {
            "timestamp": true,
            "colorize": true
        },
        "file": {
            "timestamp": true,
            "json": false,
            "prettyPrint": true,
            "outputDir": "./logs"
        }
    }
}

or

accessLogger:
  msg: 'HTTP {{req.method}} - {{res.statusCode}} - {{req.url}} ({{res.responseTime}}ms) '
  console:
    timestamp: true
    colorize: true
  file:
    timestamp: true
    json: false
    prettyPrint: true
    outputDir: "./logs"

StatsConfig

Describes the default configuration for the Stats collector. Each API can override this behavior for any kind of stats collector.

It support the following properties:

Property Type Description Required
granularity GranularityConfig The time serie granularity configuration. true
prefix string A prefix for the timeseries keys on database. false
requestMapper MiddlewareConfig A request mapper middleware to map request to statistics log entries. false

GranularityConfig

Configure the granularity of the stats collections.

It support the following properties:

Property Type Description Required
duration string The amout of time used to agregate the time series. true
ttl string Time to live for each time serie. true

You can inform the amount of milisencods, or use a human-interval string to configure both of those properties.

Example:

{
    "statsConfig": {
        "granularity": {
            "duration": "1 hour",
            "ttl": "2 days"
        }
    }
}

or

statsConfig:
  granularity:
    duration: 1 hour
    ttl: 2 days

AdminConfig

It is used in the GatewayConfig to configure the Admin Service for the Gateway.

It support the following properties:

Property Type Description Required
protocol ProtocolConfig The protocol configuration for the admin module. true
userService UsersConfig Configurations for admin users service. true
accessLogger AccessLoggerConfig Configurations for admin access log. false
disableStats boolean If true, disabled the statistical data recording for admin tasks. false
statsConfig StatsConfig Configurations for admin stats. false
apiDocs ApiDocs If provided, the service will publish all api documentation under the informed path. false
cors CorsConfig Configure cors support for Admin API requests. false
filter MiddlewareConfig[] An array of installed Filter middlewares to be executed, in order, by the request pipeline. false

UsersConfig

Configure the service used to manage the users that can access the admin tasks.

It support the following properties:

Property Type Description Required
jwtSecret string The secret or a path to a secret key used to generate JWT tokens for users authentication. true

ApiDocs

If provided, configure how to publish the api documentation.

It support the following properties:

Property Type Description Required
path string The path where deploy the docs. true
host string The hostname where swagger will point the operations. false

If the host is not provided, the swagger file will point all operations to the hostname of the machine running the service.

Example:

{
    "admin": {
        "protocol": {
            "https": {
                "listenPort": 8001,
                "privateKey": "./server.key",
                "certificate": "./server.crt"                        
            }
        },
        "accessLogger": {
            "msg": "HTTP {{req.method}} - {{res.statusCode}} - {{req.url}} ({{res.responseTime}}ms) ",
            "console": {
                "timestamp": true,
                "colorize": true
            },
            "file": {
                "timestamp": true,
                "json": false,
                "prettyPrint": true,
                "outputDir": "./logs"
            }
        },
        "userService": {
            "jwtSecret": "secret"
        },
        "apiDocs": {
            "path": "api-docs",
            "host": "localhost"
        },
        "cors" : {
            "origin": {
                "allow": [{
                    "value": "*"
                }]
            }
        }, 
        "filter": [{
            "name": "ipFilter",
            "options": {
                "whitelist": ["127.0.0.1", "::1" ]
            }
        }]
    }
}

or

admin:
  protocol:
    https:
      listenPort: 8001
      privateKey: "./server.key"
      certificate: "./server.crt"
  accessLogger:
    msg: 'HTTP {{req.method}} - {{res.statusCode}} - {{req.url}} ({{res.responseTime}}ms) '
    console:
      timestamp: true
      colorize: true
    file:
      timestamp: true
      json: false
      prettyPrint: true
      outputDir: "./logs"
  userService:
    jwtSecret: secret
  apiDocs:
    path: api-docs
    host: localhost
  cors:
    origin:
      allow:
      - value: "*"
  filter:
    - name: ipFilter 
      options: 
        whitelist: 
          - "127.0.0.1"
          - "::1"

CorsConfig

Configurations for cors requests.

It support the following properties:

Property Type Description Required
origin CorsOrigin Configures the Access-Control-Allow-Origin CORS header. true
methods string[] Configures the Access-Control-Allow-Methods CORS header. (ex: ['GET', 'PUT', 'POST']) false
allowedHeaders string[] Configures the Access-Control-Allow-Headers CORS header. (ex: ['Content-Type', 'Authorization']). If not specified, defaults to reflecting the headers specified in the request's Access-Control-Request-Headers header. false
exposedHeaders string[] Configures the Access-Control-Expose-Headers CORS header. (ex: ['Content-Range', 'X-Content-Range']). If not specified, no custom headers are exposed. false
credentials boolean Configures the Access-Control-Allow-Credentials CORS header. Set to true to pass the header, otherwise it is omitted. false
maxAge string Configures the Access-Control-Max-Age CORS header. You can inform the amount of milisencods, or use a human-interval string to pass the header, otherwise it is omitted. false
preflightContinue boolean Pass the CORS preflight response to the next handler. false

CorsOrigin

Configures the Access-Control-Allow-Origin CORS header.

It support the following properties:

Property Type Description Required
enableAll boolean If true, enable all origins to make cors requests. false
disableAll boolean If true, disable all origins to make cors requests. false
allow CorsOriginConfig[] Specify which origins are allowed. false
middleware MiddlewareConfig An installed 'cors' middleware function, called to resolve if the request should be allowed. false

All of those properties are optional, but one (and only one) of them must be present in the configuration object.

Some examples:

{
    "cors" : {
        "origin": {
            "enableAll": true
        }
    }
}

and

{
    "cors" : {
        "origin": {
            "allow": { "value": "http://example1.com"}
        },
        "methods": ["GET", "PUT", "POST"],
        "allowedHeaders": ["Content-Type", "Authorization"]
    }
}

or

cors:
  origin:
    enableAll: true

and

cors:
  origin:
    allow:
      value: http://example1.com
  methods:
  - GET
  - PUT
  - POST
  allowedHeaders:
  - Content-Type
  - Authorization

CorsOriginConfig

Configures the allowed cors origins.

It support the following properties:

Property Type Description Required
regexp string Use regular expressions to check origins that must be allowed. false
value string The origin that must be allowed. false

All of those properties are optional, but one (and only one) of them must be present in the configuration object.

Example:

{
    "cors" : {
        "origin": {
            "allow": { "regexp": "/example\\.com$/"}
        }
    }
}

or

cors:
  origin:
    allow:
      regexp: "/example\\.com$/"

This example will reflect any request that is coming from an origin ending with "example.com".

ServiceDiscovery

Configure service discovery providers to the gateway. This providers can be used by API's serviceDiscovery routers.

The Configuration has the following properties:

Property Type Description Required
provider MiddlewareConfig[] The Provider middleware configuration. true

Example:

{
    "serviceDiscovery": [
        {
            "provider": {
                "name": "consul",
                "options": {
                    "host": "localhost",
                    "port": 8500,
                    "defaults": {
                        "wait": "3 minutes"
                    } 
                }
            }
        }
    ]
}

or

serviceDiscovery:
    provider:
        - name: consul
            options:
                host: localhost
                port: 8500
                defaults: 
                    wait: 3 minutes

Pre Defined Providers

Tree Gateway provide some serviceDiscovery providers to integrate to common service discovery tools like consul.

Admin REST API

It is important that you enable the "admin" service in the "gateway" property of your tree-gateway Config File file. If you do not enable it, no configuration can be done through this gateway instance.

The following configuration enables the admin service to listen, via https, the port 8001 and expose the API docs on path https://localhost:8001/api-docs:

{
    "admin": {
        "protocol": {
            "https": {
                "listenPort": 8001,
                "privateKey": "./server.key",
                "certificate": "./server.crt"                        
            }
        },
        "userService": {
            "jwtSecret": "secret"
        },
        "apiDocs": {
            "path": "api-docs",
            "host": "localhost"
        }
    }
}

Accessing this URL https://localhost:8001/api-docs, you can see the swagger-ui interface, that allows you to explore and interact with the API.

images/rest-api.png

You can also access the API swagger file through:

http://localhost:8001/api-docs/json
or
http://localhost:8001/api-docs/yaml

You need to provide an access token to all methods on the Admin API. To obtain this token, you must authenticate with the user you created in the previous step, by calling the endpoint:

http://localhost:8001/users/authentication

Then you must inform this token through the Authorization: JWT <token> header on every Admin API request.

To do this through this swagger-ui, just follow the next steps.

Call /users/authenticate endpoint.

images/token.png

Use the user you created with userAdmin tool. The service will return a JWT token. Copy it.

Now you can authenticate through the swagger-ui interface, clicking in the red i icon that appears on every api entrypoint to indicate you need authetication. Once you click it, a dialog will be opened to you enter your credentials. Just enter JWT <your token> and authenticate.

images/auth.png

And the red icon becomes blue. You are authenticated and can call any API method.

images/authenticated.png

Node SDK

The node SDK allow you to programmatically configure tree-gateway.

Example:

const fs = require('fs-extra')
const SDK = require('tree-gateway/admin/config/sdk')
const config = require("./tree-gateway.json");

SDK.initialize(config.gateway)
  .then(sdk => {
        const pathApi = './test/data/apis/';

        // read all apis config files from a test folder and install it 
        fs.readdirAsync(pathApi)
            .then((files) => { 
                const promises = files.map(file => fs.readJsonAsync(pathApi+file));
                return Promise.all(promises);
            })
            .then((apis: any[]) => {
                const promises = apis.map(apiConfig => sdk.apis.addApi(apiConfig));
                return Promise.all(promises);
            })
            .then((apis) => {
                console.log('All APIs found on folder '+pathApi+' installed.');
            })
            .catch(reject);
  })
  .catch(error => {
      console.error('Error initializing Tree Gateway SDK': error.message);
  });

This SDK is initialized receiving the tree-gateway config object. The SDK, internaly, will call the gateway Admin Rest API in the host configured by the admin.apiDocs.host configuration property, or localhost by default.

The Node SDK also include typescript definitions (*.d.ts files) for Typescript users.

APIs Management

This will allow you to interact with your APIs. Those are some of the features you can work with:

  • Routing - configure how requests must be proxied to the target API. You can use Filters or Interceptors;
  • Authentication - configure the authentications your API will support;
  • Throttling - allows you to implement some rate limits for each of your APIs;
  • Cache - configure the cache that can be in the HTTP protocol level or a server cache, using the Redis database.
  • Circuit Breaker - allows you to configure a circuit breaker for your API, detecting failures and preventing it to reoccur constantly;
  • Cors - allows you to configure how your APIs will handle the cross-origin HTTP requests.

API Configuration

To create a new API, you can:

  • Call a POST http:localhost:8001/apis to the Rest API
  • Call sdk.apis.addApi, when using Node SDK, or
  • Call CLI command $ treeGatewayConfig -c ./tree-gateway.yaml apis --add ./myApi.json

No matters which method you are using to configure the API, you will need to provide an API configuration object that has the following properties:

Property Type Description Required
id string The API identifier. If not provided during API creation, an uuid is used. false
name string The API name. true
version string The API version. More than one version can be published for the same API name. true
path string The path where the gateway will listen for requests that should be proxied for the current API. true
description string An optional description for API. false
group Group[] Configure groups of endpoints. false
proxy Proxy Configure the proxy engine for this API. true
authentication AuthenticationConfig[] Configure authentication for this API. false
throttling ThrottlingConfig[] Configure rate limits for this API. false
cache CacheConfig[] Configure cache for this API. false
circuitBreaker CircuitBreakerConfig[] Configure a circuit breaker for this API. false
cors ApiCorsConfig[] Configure cors support for this API. false
filter Filter[] A List of request filters to be added, in order, to the request pipeline. false
errorHandler MiddlewareConfig[] An ErrorHandler middleware to be called to handle any error during request pipeline processing for this API. false

Example:

{
    "name": "TestAPI",
    "version": "1.0.0",
    "path": "test/",
    "proxy": {
        "target": {
            "host": "http://httpbin.org"
        },
        "timeout": 5000
    }
}

or,

---
name: TestAPI
version: 1.0.0
path: test/
proxy:
  target:
    host: http://httpbin.org
  timeout: 5000

That configuration will map any request to the base path /test to be proxied to http://httpbin.org.

For example, the given URLs:

  • http://localhost:8000/test/get will point to http://httpbin.org/test/get
  • http://localhost:8000/test/get?param=1 will point to http://httpbin.org/test/get?param=1

Assuming that your gateway is running on http://localhost:8000.

Group

Groups allow you to organize your configurations. They can be referenced by other API configurations, like throttling, cache (and others) to define behaviors that only apply to a specific set of endpoints.

The Group configuration supports the following properties:

Property Type Description Required
id string The Group identifier. true
member Member[] A list of group members. true
description string An optional description for the group. false

Member

Configure a member of a Group.

It supports the following properties:

Property Type Description Required
path string[] A list of request paths that belong to the group. Support glob patterns false
member string[] A list of HTTP methods that belong to the group. false
protocol string[] A list of protocols that belong to the group. false

Example:

{
    "name": "TestAPI",
    "version": "1.0.0",
    "path": "test/",
    "group": [
        {
            "id": "Group1",
            "description": "Endpoints Group One",
            "member": [
                {
                    "path": ["get"], 
                    "method": ["GET"]
                }, 
                {
                    "path": ["post"], 
                    "method": ["GET"]
                }
            ] 
        },
        {
            "id": "Group2",
            "description": "Endpoints Group Two",
            "member": [
                {
                    "path": ["user-agent"] 
                }, 
                {
                    "method": ["POST"]
                }
            ] 
        }
    ],
    "proxy": {
        "target": {
            "host": "http://httpbin.org",
            "allow": ["Group1"],
            "deny": ["Group2"]
        },
        "timeout": 5000
    }
}

or

---
name: TestAPI
version: 1.0.0
path: test/
group:
- id: Group1
  description: Endpoints Group One
  member:
  - path:
    - get
    method:
    - GET
  - path:
    - post
    method:
    - GET
- id: Group2
  description: Endpoints Group Two
  member:
  - path:
    - user-agent
  - method:
    - POST
proxy:
  target:
    host: http://httpbin.org
    allow:
    - Group1
    deny:
    - Group2
  timeout: 5000

This example show how to use groups to define rules for the proxy engine allowing or denying requests that should target the configured API.

Routing (Proxy Config)

Configure how requests must be proxied to the target API.

The Proxy configuration object must be included in the API config and supports the following properties:

Property Type Description Required
target Target The target of the proxied API. true
httpAgent HttpAgent Configure the http.Agent used by proxy requests. false
supressViaHeader boolean Tree Gateway adds a Via header on response by default. Yhis option can be used to disable it. false
interceptor Interceptors Configure request and response interceptors to be added to the request pipeline. false
preserveHostHdr boolean If true, the gateway will copy the host HTTP header to the proxied express server. false
timeout string or number Configure a specific timeout for requests. Timed-out requests will respond with 504 status code and a X-Timeout-Reason header. You can inform the amount of milisencods, or use a human-interval string false
disableStats boolean If true, disable the statistical data recording for request accesses. false
statsConfig StatsConfig Configurations for this API stats. false
limit string This sets the body size limit (default: 1mb). If the body size is larger than the specified (or default) limit, a 413 Request Entity Too Large error will be returned. See bytes.js for a list of supported formats. This option is ignored if parseReqBody is false. false
parseReqBody string or Array<string> or boolean Allows you to control when to parse the request body. Just enable it if you need to access the request.body inside a proxy middleware, like a filter or interceptor. If disabled, the request is streamed to the target API, increasing performance. You can inform the expected types of body you are expecting: ["json", "urlencoded", "raw"]. Defaults to false. false
parseCookies boolean Allows you to control when to parse the request cookies. Just enable it if you need to access the request.cookies inside a proxy middleware, like a filter or interceptor. Defaults to false. false

Target

Configure the target of the proxied API.

It supports the following properties:

Property Type Description Required
host string The proxy target host. false
router ProxyRouter A Router middleware to decide how to route the requests. false
allow string[] A list of group names that is allowed to access the target API. false
deny string[] A list of group names that is not allowed to access the target API. false

Note that you must define one of host or route properties.

Example:

{
    "proxy": {
        "target": {
            "host": "httpbin.org",
            "allow": ["Group1"],
            "deny": ["Group2"]
        },
        "timeout": "five seconds"
    }    
}

or

proxy:
  target:
    host: httpbin.org
    allow:
    - Group1
    deny:
    - Group2
  timeout: five seconds

ProxyRouter

Defines dynamic routing for the proxy through a ProxyRouter and ServiceDiscovery middlewares.

Can have the following properties:

Property Type Description Required
ssl boolean Inform if the targets returned by the middleware should be invoked using ssl (https). fasle
middleware MiddlewareConfig The ProxyRouter middleware configuration. false
serviceDiscovery MiddlewareConfig The ServiceDiscovery middleware configuration. false

Note that you must define at least one of middleware and serviceDiscovery middleware for the proxy router.

Middleware Example:

{
    "proxy": {
        "target": {
            "router": {
                "middleware": {
                    "name": "trafficSplit",
                    "options": {
                        "destinations": [{
                            "target": "http://httpbin.org", 
                            "weight": 75
                        },
                        {
                            "target": "http://httpbin.org/anything", 
                            "weight": 25
                        }]
                    }
                }
            }
        },
        "timeout": "five seconds"
    }    
}

or

proxy:
  target:
    router:
      middleware:
        name: trafficSplit
        options:
          destinations: 
            - target: http://httpbin.org
              weight: 75
            - target: http://httpbin.org/anything
              weight: 25
  timeout: five seconds

Service Discovery:

Example:

{
    "proxy": {
        "target": {
            "router": {
                "serviceDiscovery": {
                    "name": "consul",
                    "options": {
                        "serviceName": "testService"
                    }
                }
            }
        },
        "timeout": "five seconds"
    }    
}

or

proxy:
  target:
    router:
      serviceDiscovery:
        name: consul
        options:
          serviceName: testService
  timeout: five seconds

You must ensure that a service discovery provider is configured for the serviceDiscovery name consul on GatewayConfig.

You can use, also, both a proxy router and a serviceDiscovery middlewares. In this situation, the destination resolved by the proxy router is passed as input to the serviceDiscovery middleware. For example:

{
    "proxy": {
        "target": {
            "router": {
                "middleware": {
                    "name": "trafficSplit",
                    "options": {
                        "destinations": [
                            {
                                "target": "testService_v1",
                                "weight": 97
                            },
                            {
                                "target": "testService_v2",
                                "weight": 3
                            }
                        ]
                    }
                },
                "serviceDiscovery": {
                    "name": "consul",
                    "options": {
                        "serviceName": "testService",
                        "loadBalancer": "round-robin"
                    }
                }
            }
        },
        "timeout": "five seconds"
    }
}

or

proxy:
  target:
    router:
      middleware:
        name: trafficSplit
        options:
          destinations: 
            - target: testService_v1
              weight: 97
            - target: testService_v2
              weight: 3
      serviceDiscovery:
        name: consul
        options:
          serviceName: testService
          loadBalancer: round-robin
  timeout: five seconds

This last example will route the requests sending 97% of the requests to the service testService_v1 and only 3% for the testService_v2. Then the service discovery middleware will find available nodes for the requested service and use a round-robin load balancer to choose one between these nodes.

Advanced Routing

Tree Gateway provide some middlewares to perform common tasks like request or response body transformations, traffic spliting, ip filtering and service discovery.

HttpAgent

Configure the http.Agent used by proxy requests.

Can have the following properties:

Property Type Description Required
keepAlive boolean Keep sockets around in a pool to be used by other requests in the future. Defaults to true. fasle
keepAliveTime string or number When using HTTP KeepAlive, how often to send TCP KeepAlive packets over sockets being kept alive. You can inform the amount of milisencods, or use a human-interval string. Default = 'one second'. Only relevant if keepAlive is set to true. fasle
freeSocketKeepAliveTimeout string or number Sets the free socket to timeout after freeSocketKeepAliveTimeout milliseconds of inactivity on the free socket. You can inform the amount of milisencods, or use a human-interval string. Default is '15 seconds'. Only relevant if keepAlive is set to true. fasle
timeout string or number Sets the working socket to timeout after timeout milliseconds of inactivity on the working socket. You can inform the amount of milisencods, or use a human-interval string. Default is freeSocketKeepAliveTimeout * 2. fasle
maxSockets number Maximum number of sockets to allow per host. Default = Infinity. fasle
maxFreeSockets number Maximum number of sockets to leave open in a free state. Only relevant if keepAlive is set to true. Default = 256. fasle

Example:

{
    "proxy": {
        "target": {
            "host": "http://localhost:9000"
        },
        "httpAgent": {
            "keepAlive": true,
            "keepAliveTime": "one second",
            "freeSocketKeepAliveTimeout": "30 seconds",
            "maxFreeSockets": 10,
            "maxSockets": 200,
            "timeout": "one minute"
        }
    }
}

or

proxy:
  target:
    host: http://localhost:9000
  httpAgent:
    keepAlive: true
    keepAliveTime: one second
    freeSocketKeepAliveTimeout: 30 seconds
    maxFreeSockets: 10
    maxSockets: 200
    timeout: one minute

Interceptors

Configure request and response to the request pipeline.

It supports the following properties:

Property Type Description Required
request Interceptor[] A list of request interceptor names true
response Interceptor[] A list of response interceptor names true

Interceptor

Configure a request or response interceptor.

It supports the following properties:

Property Type Description Required
middleware MiddlewareConfig The Interceptor configuration. true
group string[] A list of group names that should be intercepted by this interceptor. If not provided, everything will be intercepted. false

Example:

{
    "proxy": {
        "target": {
            "host": "http://httpbin.org"
        },
        "interceptor": {
            "request": [
                {
                    "middleware": {
                        "name":"myRequestInterceptor"
                    }, 
                    "group": ["Group1"]
                },
                {
                    "middleware": {
                        "name":"mySecondRequestInterceptor"
                    }
                }
            ], 
            "response": [
                {
                    "middleware": {
                        "name":"myResponseInterceptor"}
                    }, 
                {
                    "middleware": {
                        "name":"SecondInterceptor"
                    }, "group": ["Group1"]
                }
            ] 
        },
        "timeout": 5000
    }
}

or

proxy:
  target:
    host: http://httpbin.org
  interceptor:
    request:
    - middleware:
        name: myRequestInterceptor
      group:
      - Group1
    - middleware:
        name: mySecondRequestInterceptor
    response:
    - middleware:
        name: myResponseInterceptor
    - middleware:
        name: SecondInterceptor
      group:
      - Group1
  timeout: 5000

Advanced Routing

Tree Gateway provides some pre defined middlewares to support advanced proxy features:

Proxy Routers

Router Description
loadBalancer Support load balancing for the possible targets.
trafficSplit Support traffic splitting using weights for the possible targets.
query Support route the destination, based on a query parameter in the request.
header Support route the destination, based on a header in the request.

Filters

Filter Description
ipFilter Support ip filtering using whitelists and blacklists that can be updated from a database.

Interceptors

Interceptor Description
requestBodyTransformer Use jsonata expressions to transform request body.
responseBodyTransformer Use jsonata expressions to transform response body.
requestHeaders Allow to add / update or remove a request header, before send it to destination.
responseHeaders Allow to add / update or remove a response header, before send it to client.
requestXml Transform a javascript object (or a json string) in the body of the request to a XML string.
responseXml Transform a XML string in the body of the request into a javascript object.
requestMustache Use the object in the request body as a parameter to be applied to a mustache template. The result is the new request body.
responseMustache Use the object in the response body as a parameter to be applied to a mustache template. The result is the new response body.
webSecurity Add some response headers to increase the API security, protecting it from common attacks.

Service Discovery

Interceptor Description
consul Consult consul registry to find out the target destination for the request.

Authentication

Configure authentication for API requests.

Tree gateway uses passportjs to handle authentication.

The Authentication configuration object must be included in the API config and supports the following properties:

Property Type Description Required
strategy MiddlewareConfig The middleware that construct the strategy for authentication. true
disableStats boolean If true, disable the statistical data recording for authentication events. false
statsConfig StatsConfig Configurations for the authentication stats. false

Pre defined Authentications

Tree gateway provides some middlewares already installed for most common authentication strategies:

It is possible to use one of the pre defined authentication strategies, or to define your own, using a middleware.

Example (Custom):

{
    "authentication": {
        "strategy": {
            "name": "myJwtStrategy",
            "options": {
                "secret": "secret"
            }
        }
    }
}

The custom example above will use a middleware named myJwtStrategy, that must be installed to perform the authentication. The object configurated will be passed as parameter to the middleware initialization function:

{
    "secret": "secret"
}

Note that you can pass anything you need here.

Basic

Configure a authentication to use the http basic strategy.

It support the following option properties:

Property Type Description Required
verify MiddlewareConfig A middleware that check the credentials and call done with the authenticated user object. true

The verify middleware should receive the following parameters:

  • userid: The username.
  • password: The password.
  • done: is a passport error first callback accepting arguments done(error, user, info)

Example:

{
    "authentication": {
        "strategy": {
            "name": "basic",
            "options": {
                "verify": {
                    "name": "verifyBasicUser"
                }
            }
        }
    }
}

Local

Configure a authentication to use the local strategy.

It support the following properties:

Property Type Description Required
verify MiddlewareConfig A middleware that check the credentials and call done with the authenticated user object. true
usernameField string The name of the form field that informs the username. Defaults to 'username' false
passwordField string The name of the form field that informs the password. Defaults to 'password' false

The verify middleware should receive the following parameters:

  • userid: The username.
  • password: The password.
  • done: is a passport error first callback accepting arguments done(error, user, info)

Example:

{
    "authentication": {
        "strategy": {
            "name": "local", 
            "options": {
                "usernameField": "userid",
                "passwordField": "passwd",
                "verify": {
                    "name": "verifyBasicUser"
                }
            }
        }    
    }
}

JWT

Configure a authentication to use the JWT strategy.

It support the following properties:

Property Type Description Required
secretOrKey string Is a string containing the secret (symmetric) or PEM-encoded public key (asymmetric) for verifying the token's signature. true
extractFrom JWTRequestExtractor Defines how the JWT token will be extracted from request. false
issuer string If defined the token issuer (iss) will be verified against this value. false
audience string If defined, the token audience (aud) will be verified against this value. false
algorithms string[] List of strings with the names of the allowed algorithms. For instance, ["HS256", "HS384"]. false
ignoreExpiration boolean If true do not validate the expiration of the token. false
verify MiddlewareConfig A middleware that check the credentials and call done with the authenticated user object. false

The verify middleware should receive the following parameters:

  • request: The user request.
  • jwt_payload: Is an object literal containing the decoded JWT payload.
  • done: Is a passport error first callback accepting arguments done(error, user, info)

JWTRequestExtractor

Configure how the JWT token will be extracted from request.

It support the following properties:

Property Type Description Required
header string The name of the header that contains the token. false
queryParam string The name of the param that contains the token. false
authHeader string The name of shcema used in Authorization header. Ex: 'JWT'. false
bodyField string The name of the form param that contains the token. false
cookie string The name of the cookie that contains the tolen. false

Example:

{
    "authentication": {
        "strategy": {
            "name": "jwt",
            "options": {
                "extractFrom": {
                    "authHeader": "Bearer",
                    "queryParam": "jwt"
                },
                "secretOrKey": "secret",
                "algorithms": ["HS256", "HS384"],
                "ignoreExpiration": true,
                "verify": {
                    "name": "verifyJwtUser"
                }
            }
        } 
    }
}

Throttling (Rate Limits)

Configure throttling (Rate Limits) for API requests.

The Throttling configuration object must be included in the API config and supports the following properties:

Property Type Description Required
timeWindow string or number How long to keep records of requests in memory. You can inform the amount of milisencods, or use a human-interval string. Defaults to '1 minute' false
delayAfter number Max number of connections during timeWindow before starting to delay responses. false
delay string or number How long to delay the response, multiplied by (number of recent hits - delayAfter). You can inform the amount of milisencods, or use a human-interval string false
max number Max number of connections during timeWindow before sending a 429 response. Defaults to 5. false
message string Error message returned when max is exceeded. Defaults to 'Too many requests, please try again later.' false
statusCode number HTTP status code returned when max is exceeded. Defaults to 429. false
headers boolean If true, enable header to show request limit and current usage. false
keyGenerator MiddlewareConfig An installed 'throttling/keyGenerators' middleware function, called to identify the source of the request. By default user IP address (req.ip) is used as key. false
skip MiddlewareConfig An installed 'throttling/skip' middleware function, called to verify if the throttling engine should not intercept some requests. false
handler MiddlewareConfig An installed 'throttling/handlers' middleware function, called when the max limit is exceeded. false
disableStats boolean If true, disable the statistical data recording for throttling events. false
statsConfig StatsConfig Configurations for the throttling stats. false

Example:

 {
    "throttling": {
            "timeWindow": "one minute",
            "max": 100,
            "delayAfter": 90,
            "delay": "1 second",
            "keyGenerator": {
                "name": "myThrollingKeyMiddleware"
            }
        }
 }

Cache

Configure cache for API requests.

The Caching system supports two kinds of cache (and both can be used together or alone):

  • Browser cache): The gateway can handle HTTP response headers to make the client browsers keep a cache for configured resources.
  • Memory Cache: The gateway save copies of the proxied API responses into the Redis database.

The Cache configuration object must be included in the API config and supports the following properties:

Property Type Description Required
client ClientCacheConfig Configuration for a client side cache (in browser). false
server ServerCacheConfig Configuration for a server side cache (in a Redis store). false

ClientCacheConfig

Configure HTTP response headers to make the client browsers keeping a cache for configured resources.

It support the following properties:

Property Type Description Required
cacheTime string or number The time to keep the cached resources. You can inform the amount of milisencods, or use a human-interval string. true
cacheControl 'public', 'private', 'no-cache' or 'no-store' Configure the HTTP Cache-Control header. false
mustRevalidate boolean Configure the HTTP Cache-Control header. false
noTransform boolean Configure the HTTP Cache-Control header. false
proxyRevalidate boolean Configure the HTTP Cache-Control header. false

Example:

{
    "cache": {
            "client": {
                "cacheTime": "1 minute",
                "cacheControl": "public",
                "mustRevalidate": false,
                "noTransform": false,
                "proxyRevalidate": false
            }
        }
}

ServerCacheConfig

Configure the caching system to save copies of the proxied API responses into the Redis database.

It support the following properties:

Property Type Description Required
cacheTime string or number The time to keep the cached resources. You can inform the amount of milisencods, or use a human-interval string. true
preserveHeaders string[] A list of response received headers that also need to be saved by cache system, to reproduce them to clients. false
disableStats boolean If true, disable the statistical data recording for cache events. false
statsConfig StatsConfig Configurations for the cache stats. false

Example:

{
    "cache": {
            "client": {
                "cacheTime": "1 minute",
                "cacheControl": "public",
            },
            "server": {
                "cacheTime": "10 minutes",
                "binary": true,
                "preserveHeaders" :["access-control-allow-credentials"]
            }
        }
}

Circuit Breaker

Configure circuit breaker for API requests.

The Circuitbreaker configuration object must be included in the API config and supports the following properties:

Property Type Description Required
timeout string or number Exceptions or calls exceeding the configured timeout increment a failure counter. You can inform the amount of milisencods, or use a human-interval string. Defaults to '30 seconds'. false
resetTimeout string or number After the configured resetTimeout, the circuit breaker enters a 'half-open' state. You can inform the amount of milisencods, or use a human-interval string. Defaults to '2 minutes'. false
timeWindow Define a time window to count the api failures. If defined, the gateway will reset the total failures count by each period of time defined here. false
maxFailures number When the failure counter reaches a maxFailures count, the breaker is tripped into 'open' state. false
disableStats boolean If true, disable the statistical data recording for circuitbreaker events. false
statsConfig StatsConfig Configurations for circuitbreaker stats. false
onOpen MiddlewareConfig An installed 'circuitbreaker' middleware function, called when the circuit move to 'open' state. false
onClose MiddlewareConfig An installed 'circuitbreaker' middleware function, called when the circuit move to 'close' state. false
onRejected MiddlewareConfig An installed 'circuitbreaker' middleware function, called when the circuit rejected (fast fail) a request. false
timeoutMessage string Message to be sent when an api call occurs in a timeout. Defaults to: 'Operation timeout'. false
timeoutStatusCode number Status code to be sent when an api call occurs in a timeout. Defaults to: 504. false
rejectMessage string Message to be sent when an api call is rejected because circuit is open. Defaults to: 'Service unavailable'. false
rejectStatusCode number Status code to be sent when an api call is rejected because circuit is open. Defaults to: 503. false

Example:

{
    "circuitBreaker": {
        "timeout": "45 seconds",
        "resetTimeout": "2 minutes and 30 seconds",
        "maxFailures": 10,
        "onOpen": {
            "name": "myOpenHandler"
        }
    }
}

Cors

Configurations for cors on API requests.

This configuration object extends the CorsConfig and adds the following properties:

Property Type Description Required
group string[] A list of group names that should be handled by this configuration. If not provided, everything will be handled. false

Example:

{
    "cors" : [{
        "origin": {
            "allow": { "value": "http://example1.com"}
        },
        "methods": ["GET", "PUT", "POST"],
        "allowedHeaders": ["Content-Type", "Authorization"],
        "group": ["Group1", "Group3"]

    },
    {
        "origin": {
            "allow": { "regexp": "/example\\.com$/"}
        },
        "methods": ["PUT", "POST"],
        "group": ["Group2"]
    }]
}

Filter

Configure request filters to the request pipeline. If you configure more than one filter, they are all applied following the same order as defined here into this list.

Each Filter Configuration has the following properties:

Property Type Description Required
middleware MiddlewareConfig The Filter configuration. true
group string[] A list of group names that should be filtered by this filter. If not provided, everything will be filtered. false

Example:

{
    "filter": [
        {
            "middleware": {
                "name": "myCustomFilter"
            },
            "group": ["Group1"]
        },
        {
            "middleware": {
                "name": "mySecondFilter"
            },
            "group": ["Group2"]
        }
    ]
}

or

filter:
  - middleware:
      name: myCustomFilter
    group:
      - Group1
  - middleware:
      name: mySecondFilter
    group:
      - Group2

Pre Defined Filters

Tree Gateway provide some filters to perform common tasks like ip filtering.

Advanced Routing

Tree Gateway provides some pre defined middlewares to support advanced proxy features:

Proxy Routers

Router Description
loadBalancer Support load balancing for the possible targets.
trafficSplit Support traffic splitting using weights for the possible targets.
query Support route the destination, based on a query parameter in the request.
header Support route the destination, based on a header in the request.

Filters

Filter Description
ipFilter Support ip filtering using whitelists and blacklists that can be updated from a database.

Interceptors

Interceptor Description
requestBodyTransformer Use jsonata expressions to transform request body.
responseBodyTransformer Use jsonata expressions to transform response body.
requestHeaders Allow to add / update or remove a request header, before send it to destination.
responseHeaders Allow to add / update or remove a response header, before send it to client.
requestXml Transform a javascript object (or a json string) in the body of the request to a XML string.
responseXml Transform a XML string in the body of the request into a javascript object.
requestMustache Use the object in the request body as a parameter to be applied to a mustache template. The result is the new request body.
responseMustache Use the object in the response body as a parameter to be applied to a mustache template. The result is the new response body.
webSecurity Add some response headers to increase the API security, protecting it from common attacks.

Service Discovery

Interceptor Description
consul Consult consul registry to find out the target destination for the request.

Other Middlewares

Tree Gateway provides some pre defined middlewares:

Error Handlers

Middleware Description
json Create a json response using a jsonata expression and the error object.
mustache Create an error response using a mustache template and the error object.

Stats Request Mappers

Middleware Description
path Use the request.path as an agregator for the request statistcs.
operation Use a combination fo request.method and request.path as an agregator for the request statistcs.
total Aggregates all reqeusts to the same API together.

Middlewares

Middlewares are functions that allow you to customize some step of the request pipeline, such as Routing, Authentication, Throttling and so on.

Tree Gateway support different kinds of middleware:

  • Filter - run before the request pipeline and decide if the request should or not be processed;
  • Cors - you can define white and black lists, specific rules and so on for handle cor requests;
  • Request and Response interceptors - allow you to customize your requests and responses information, such as headers, content body and others;
  • Throttling - allow you to create a custom way to identify the source of your requests, to be used by the rate limit engine;
  • Authentication - allows you to instantiate any passportjs strategy to satisfy a custom authentication method;
  • Service Discovery - Integrate a service discovery provider, like consul, to your request pipeline to define the target of your service requests;
  • Circuit Breaker - allows you to customize actions whenever some circuit breaker event occurs, such as 'open', 'close' or 'rejected'.
  • Error Handler - allow you to customize all error messages.

When defining a middleware, you must create a .js file that exports the middleware function, like:

module.exports = function (request, response) {
  return req.query.denyParam !== '1';
};

Sometimes, your middlewares can need to receive parameters to be initialized. Those middlewares need to:

  • be exported as a function that receives the option parameter and return the initialized middleware.
  • have a property factory=1exported too.

Example:

module.exports = function(options) {
  return function (request, response) {
    return options.allowedValues.indexOf(req.query.denyParam) < 0;
  };
};
module.exports.factory = true;

Cors Handler

A Cors middleware is a function that receives the request origin from the gateway and must return a boolean value (or a Promise) to inform if the given origin is allowed.

Each filter must be defined on its own .js file.

Example:

/**
 * @param origin the origin extracted from request.
 */
module.exports = function (origin) {
    return (whitelist.indexOf(origin) !== -1);
};

or, using Promises:

module.exports = function (origin) {
    return new Promise((resolve, reject) => {
        setTimeout(function(){resolve(whitelist.indexOf(origin) !== -1);}, 10);
    });
};

You can configure a cors middleware through:

  • Admin Rest API: POST /cors
  • SDK: sdk.middleware.addCors(name, fileName);
  • CLI: treeGatewayConfig middleware cors -a <name> ./filename.js

Request Filter

A Filter is a function that receives the request and the response object from the gateway and must return a boolean value (or a Promise<boolean>) to inform if the given request should target the destination API or if it should be ignored.

Each filter must be defined on its own .js file.

Example:

/**
 * Where request and response are the original request and response objects created by [http](https://nodejs.org/api/http.html) module.
 */
module.exports = function (request, response) {
  return req.query.denyParam !== '1';
};

or, using Promises:

/**
 * Where request and response are the original request and response objects created by [http](https://nodejs.org/api/http.html) module.
 */
module.exports = function (request, response) {
  return new Promise((resolve, reject) => {
    setTimeout(function(){resolve(req.query.denyParam !== '1');}, 10);
  };
};

You can configure a request filter middleware through:

  • Admin Rest API: POST /midleware/filters
  • SDK: sdk.middleware.addFilter(name, fileName);
  • CLI: treeGatewayConfig middleware filter -a <name> ./filename.js

Tree Gateway provide some filter middlewares for common tasks already included in its distribution. Check the list here.

Request Interceptor

A Request Interceptor is a function that receives two an object representing the request that will be sent by the proxy, targeting the destination API.

The interceptor must return an object containing the properties that needs to be overwriten in the proxy request.

The proxy request object contains the following properties:

Property Type Description Required
body any If proxy.parseReqBody is true, contains the parsed request body. false
headers any An object contaning the headers to be added to the request. false
method string The HTTP method to be used in the proxy request. false
url string The url path of the request under the target destination API. false

It is also possible to return a Promise.

Each interceptor must be defined on its own .js file.

Example:

/**
 * Where proxyReq and userlReq are request objects created by [http](https://nodejs.org/api/http.html) module.
 * @param proxyReq the request that is being created by the proxy engine targeting the destination API.
 * @param userReq the request received by the gateway from the client.
 */
module.exports = function(proxyReq) {
   // you can update headers
   proxyReq.headers['Content-Type'] = 'text/html';
   // you can change the method
   proxyReq.method = 'GET';
   // you can munge the bodyContent.
   proxyReq.body = proxyReq.body.toString().replace(/losing/, 'winning!');

   return proxyReq;
};

or

module.exports = function(request) {
   return new Promise((proxyReq, reject) => {
      var data = JSON.parse(proxyReq.toString('utf8'));
      var newHeaders = Object.assign(request.headers, {
          mySpecialHeader: 'header value',
          myOtherSpecialHeader: 'header value 2'
      });

      resolve({body: data, headers: newHeaders, url: '/changedPath'});
   });
};

Note that to be able to access the request body, you must set the parseReqBody to true on the proxy config.

You can configure a request interceptor middleware through:

  • Admin Rest API: POST /midleware/interceptors/request
  • SDK: sdk.middleware.addRequestInterceptor(name, fileName);
  • CLI: treeGatewayConfig middleware requestInterceptor -a <name> ./filename.js

Tree Gateway provide some interceptor middlewares for common tasks already included in its distribution. Check the list here.

Response Interceptor

A Response Interceptor is a function that receives the following parameters:

  • body: the body of the response received from the destination API.
  • headers the response headers to be sent by the gateway to the client.
  • request: the request received by gateway from the client.

The interceptor must return an object containing:

Property Type Description Required
body any If provided, modify the response body. false
updateHeaders any An object contaning the headers to be added to the response. If the response already includes one of those headers, they will be overwritten. false
removeHeaders string[] A list of headers that must be suprresed from the response. false

It is also possible to return a Promise.

Each interceptor must be defined on its own .js file.

Example:

/**
 * Where request is the object created by [http](https://nodejs.org/api/http.html) module.
 * @param body the body of the response received from the destination API.
 * @param headers the response headers to be sent by the gateway to the client.
 * @param request the request received by gateway from the client.
 * @return An object that can contains: 
 *  - body: the response body,
 *  - updateHeaders: inform a list of headers to be included into the response 
 *  - removeHeaders: a list of headers to be suppressed.
 */
module.exports = function(body, headers, request) {
   var data = JSON.parse(body.toString('utf8'));
   var newHeaders = {
      mySpecialHeader: 'header value',
      myOtherSpecialHeader: 'header value 2'
   };
   return {body: data, updateHeaders: newHeaders, removeHeaders: ['excludedHeader']};
};

or

module.exports = function(body, headers, request) {
   return new Promise((resolve, reject) => {
      var data = JSON.parse(body.toString('utf8'));
      var newHeaders = {
          mySpecialHeader: 'header value',
          myOtherSpecialHeader: 'header value 2'
      };
      resolve({body: data, updateHeaders: newHeaders, removeHeaders: ['excludedHeader']});
   });
};

If the response already includes one of those headers, they will be overwritten.

You can configure a request interceptor middleware through:

  • Admin Rest API: POST /midleware/interceptors/response
  • SDK: sdk.middleware.addResponseInterceptor(name, fileName);
  • CLI: treeGatewayConfig middleware responseInterceptor -a <name> ./filename.js

Tree Gateway provide some interceptor middlewares for common tasks already included in its distribution. Check the list here.

Auth Strategy

An Authentication Strategy middleware is a function than can instantiate any passportjs strategy to satisfy a custom authentication method.

This functions receives a paramenter with any custom configurations you desire to pass when registering the middlware inside an API Authentication.

Each middleware must be defined on its own .js file.

Example:

'use strict';

var JwtStrategy = require('passport-jwt').Strategy,
    ExtractJwt = require('passport-jwt').ExtractJwt;

/**
 * You can define your own passportjs strategy here.
 * @param authConfig - Constains any configuration you inform on your API Authentication configuration.
 */
module.exports = function (authConfig) {
    var opts = {}
    opts.jwtFromRequest = ExtractJwt.fromUrlQueryParameter('jwt');
    opts.secretOrKey = authConfig.secret;
    return new JwtStrategy(opts, function(jwt_payload, done) {
        done(null,jwt_payload.sub);
    });
};

For instance, if you configure the authentication of your API like:

{
    "authentication": {
        "strategy": {
            "name": "myJwtStrategy",
            "options": {
                "secret": "secret"
            }
        }
    }}

The middleware function will receive as paramater:

{
    "secret": "secret"
}

You can configure an auth strategy middleware through:

  • Admin Rest API: POST /midleware/authentication/strategies
  • SDK: sdk.middleware.addAuthStrategy(name, fileName);
  • CLI: treeGatewayConfig middleware authStrategy -a <name> ./filename.js

Auth Verify

An Authentication Verify is a function than can be used by the authentication strategy to verify parameters and build the authenticated user object.

Tree Gateway provides 3 pre configured strategies:

These strategies support the use of a verify function, but depending on the strategy adopted, the verify middleware function will receive different parameters.

Each middleware must be defined on its own .js file.

JWT

The JWT verify function receives the following parameters:

  • request: The request received from client by the gateway.
  • jwt_payload: The payload extracted from the JWT token received (already validated).
  • done_callback: A callback function, following the convention: callback(error, value). Where value will be the user object injected into request.user property.

Example:

/**
 * @param request The request received from client by the gateway.
 * @param jwt_payload The payload extracted from the JWT token received (already validated).
 * @param done A callback function, following the convention: callback(error, value). Where 
 * value will be the user object injected into request.user property.
 */
 */
module.exports = function (request, jwt_payload, done){
    console.log('Custom verify function called.');
    done(null, jwt_payload);
};

Basic and Local

The Basic and Local verify function receives the following parameters:

  • userid: The username provided by user.
  • password: The password provided by user.
  • done: A callback function, following the convention: callback(error, value). Where value will be the user object injected into request.user property.

Example:

const User = require('./my-user-service');

/**
 * @param userid The username provided by user.
 * @param password The password provided by user.
 * @param done A callback function, following the convention: callback(error, value). Where 
 * value will be the user object injected into request.user property.
 */
 */
module.exports = function (userid, password, done){
    // console.log('Custom verify function called.');
    User.findOne({ username: userid }, function (err, user) {
      if (err) { return done(err); }
      if (!user) { return done(null, false); }
      if (!user.verifyPassword(password)) { return done(null, false); }
      return done(null, user);
    });
};

You can configure an auth verify middleware through:

  • Admin Rest API: POST /midleware/authentication/verify
  • SDK: sdk.middleware.addAuthVerify(name, fileName);
  • CLI: treeGatewayConfig middleware authVerify -a <name> ./filename.js

Throttling Key

A Throttling KeyGenerator middleware is a function that creates a key for the throttling engine to identify the source of the request. It receives the following parameters:

  • request: The request received by the Gateway from the user.

Each middleware must be defined on its own .js file.

Example:

/**
 * @param request The request received by the Gateway from the user.
 */
module.exports = function (request) {
    return request.ip;
};

The above function is the default function used as key generator for the throttling.

You can configure a KeyGenerator middleware through:

  • Admin Rest API: POST /midleware/throttling/keyGenerators
  • SDK: sdk.middleware.addThrottlingKeyGenerator(name, fileName);
  • CLI: treeGatewayConfig middleware throttlingKeyGenerator -a <name> ./filename.js

Throttling Handler

A Throttling Handler middleware is a function executed when the throttling max limit is exceeded. It receives the following parameters:

  • request: The request received by the Gateway from the user.
  • response: The response to be sent by the Gateway to the user.
  • next: The express next function, if you need to pass to the next middleware.

Each middleware must be defined on its own .js file.

Example:

/**
 * @param request The request received by the Gateway from the user.
 * @param response The response to be sent by the Gateway to the user.
 * @param next The [express](http://expressjs.com) next function, if you need to pass to the next middleware.
 */
module.exports = function (request, response, next) {
  response.format({
     html: function(){
        response.status(options.statusCode).end(options.message);
     },
     json: function(){
        response.status(options.statusCode).json({ message: options.message });
     }
  });
};

The above function is the default function used as handler for the throttling.

You can configure a Handler middleware through:

  • Admin Rest API: POST /midleware/throttling/handlers
  • SDK: sdk.middleware.addThrottlingHandler(name, fileName);
  • CLI: treeGatewayConfig middleware throttlingHandler -a <name> ./filename.js

Throttling Skip

A Throttling Skip middleware is a function used to skip requests. Returning true from the function will skip limiting for that request.

It receives the following parameters:

  • request: The request received by the Gateway from the user.
  • response: The response to be sent by the Gateway to the user.

Each middleware must be defined on its own .js file.

Example:

/**
 * @param request The request received by the Gateway from the user.
 */
module.exports = function (request, response) {
    return false;
};

The above function is the default function used as skip for the throttling.

You can configure a Skip middleware through:

  • Admin Rest API: POST /midleware/throttling/skip
  • SDK: sdk.middleware.addThrottlingSkip(name, fileName);
  • CLI: treeGatewayConfig middleware throttlingSkip -a <name> ./filename.js

Circuit Breaker Handler

A CircuitBreaker Handler middleware is a function called when circuitbreaker events occurs. The events cal be a state change('open' or 'close') or a request rejection due to a circuit 'open' state.

It receives the following parameters:

  • apiPath: The path being called to target API.
  • event: The event that originated the call. Can be 'open', 'close' or 'rejected'.

Each middleware must be defined on its own .js file.

Example:

/**
 * @param apiPath The path being called to target API.
 * @param event The event that originated the call. Can be 'open', 'close' or 'rejected'.
 */
module.exports = function (apiPath, event) { 
    sendEmail('Event received: '+ event, apiPath);
};

You can configure a circuitbreaker handler middleware through:

  • Admin Rest API: POST /midleware/circuitbreaker
  • SDK: sdk.middleware.addCircuitBreaker(name, fileName);
  • CLI: treeGatewayConfig middleware circuitbreaker -a <name> ./filename.js

Proxy Routers

A Router is a function that receives the request object and must return a string value (or a Promise<string>) to inform the target destination for this proxy.

Each router must be defined on its own .js file.

Example:

/**
 * Where request is the original request received by the gateway.
 */
module.exports = function (request) {
  return req.query.version == '2'? 'http://myapiversiontwo/':'http://myapiversionone/';
};

or, using Promises:

module.exports = function (request) {
  return new Promise((resolve, reject) => {
    setTimeout(function(){resolve(req.query.version == '2'? 'http://myapiversiontwo/':'http://myapiversionone/');}, 10);
  };
};

You can configure a proxy router middleware through:

  • Admin Rest API: POST /midleware/proxy/router
  • SDK: sdk.middleware.addProxyRouter(name, fileName);
  • CLI: treeGatewayConfig middleware proxyRouter -a <name> ./filename.js

Tree Gateway provide some router middlewares for common tasks already included in its distribution. Check the list here.

Service Discovery

A ServiceDiscovery is a function that receives the desired service name and must return a string value (or a Promise<string>) to inform the target destination for this proxy.

The serviceDiscovery middleware is initialized receiving a config parameter that will receive any options declared in your middleware configuration plus two configurations:

Property Type Description Required
clientAgent any The client created by the serviceDiscovery provider middleware. true
ssl boolean True if the requests to the target service must use SSL (https). false

Each serviceDiscovery middleware must be defined on its own .js file.

Example:

/**
 * Where config contains a reference by the clientAgent created by the serviceDiscovery provider and a ssl flag
 */
module.exports = function (config) {  
  return (serviceName) => {
    return (config.ssl?'https://':'http://') + 
             config.clientAgent.get(serviceName).address + ':' +
             config.clientAgent.get(serviceName).port;
  };
};

or, using Promises:

module.exports = function (config) {
  return (serviceName) => {
    return new Promise((resolve, reject) => {
      config.clientAgent.get(serviceName)
        .then(service => {
          resolve((config.ssl?'https://':'http://') + service.address + ': ' + service.port)
        }).catch(reject);
    };
  }
};

You must remeber to configure a serviceDiscovery provider middleware to initialize the clientAgent, used to interact with the service registry.

You can configure a serviceDiscovery middleware through:

  • Admin Rest API: POST /midleware/servicediscovery
  • SDK: sdk.middleware.addServiceDiscovery(name, fileName);
  • CLI: treeGatewayConfig middleware serviceDiscovery -a <name> ./filename.js

Tree Gateway provide some service discovery middlewares for common tasks already included in its distribution. Check the list here.

Service Discovery Provider

A ServiceDiscovery Provider is a function that must return a client (or a Promise<any>) to be used to serviceDiscovery middlewares to search for services.

Each serviceDiscovery provider middleware must be defined on its own .js file.

Example:

/**
 */
module.exports = function(config) {
    validateConfig(config);
    const client = new MyClient(config);
    return () => {
        return client;
    };
};

or, using Promises:

module.exports = function (config) {
  return () => {
    return new Promise((resolve, reject) => {
    const client = new MyClient(config);
      config.init(config)
        .then(resolve)
        .catch(reject);
    };
  }
};

You can configure a serviceDiscovery Provider middleware through:

  • Admin Rest API: POST /midleware/servicediscovery/provider
  • SDK: sdk.middleware.addServiceDiscoveryProvider(name, fileName);
  • CLI: treeGatewayConfig middleware serviceDiscoveryProvider -a <name> ./filename.js

Tree Gateway provide some service discovery middlewares for common tasks already included in its distribution. Check the list here.

Error Handler

An ErrorHandler is a function that is called to handle all errors reported by the gateway.

The ErrorHandler middleware should be a valid expressjs error handler function.

Each errorHandler middleware must be defined on its own .js file.

Example:

module.exports = (err, req, res, next) => {
    if (err && err.message) {
        if (res.headersSent) { // important to allow default error handler to close connection if headers already sent
            return next(err);
        }
        const mime = req.accepts('json', 'xml', 'html', 'text');
        res.status(err.statusCode || err.status || 500);
        switch (mime) {
            case 'json':
                res.set('Content-Type', 'application/json');
                res.json({ error: err.message });
                break;
            case 'xml':
                res.set('Content-Type', 'application/xml');
                res.send(`<error>${err.message}</error>`);
                break;
            case 'html':
                res.set('Content-Type', 'text/html');
                res.send(`<html><head></head><body>${err.message}</body></html>`);
                break;
            default:
                res.set('Content-Type', 'text/plain');
                res.send(err.message);
        }
    } else {
        next(err);
    }
};

If you need to receive some parameters to initialize your error handler, you can write a factory function, like:

module.exports = function(config) {
    validateMustacheConfig(config);
    const template = config.template;
    return (err, req, res, next) => {
        if (err && err.message) {
            if (res.headersSent) { 
                return next(err);
            }
            res.set('Content-Type', config.contentType || 'text/html');
            res.status(err.statusCode || err.status || 500);

            let body;
            try {
                body = mustache.render(template, {
                    error: err,
                    req: req,
                    res: res
                });
            } catch (e) {
                body = { error: err.message };
            }
            res.send(body);
        } else {
            next(err);
        }
    };
};
module.exports.factory = true;

You can configure an errorHandler middleware through:

  • Admin Rest API: POST /midleware/errorhandler
  • SDK: sdk.middleware.addErrorHandler(name, fileName);
  • CLI: treeGatewayConfig middleware errorHandler -a <name> ./filename.js

Tree Gateway provide some error handler middlewares for common tasks already included in its distribution. Check the list here.

Stats Request Mapper

A Request Mapper is a function that is called to map requests into log entries. This function returns a string for a given request. Tha string is used to aggregate the collected statistics.

Each request mapper middleware must be defined on its own .js file.

Example:

module.exports = (req) => {
    return `${req.method} - ${normalizePath(req.path)}`;
};

You can configure an requestMapper middleware through:

  • Admin Rest API: POST /midleware/stats/request/mapper
  • SDK: sdk.middleware.addStatsRequestMapper(name, fileName);
  • CLI: treeGatewayConfig middleware statsRequestMapper -a <name> ./filename.js

Tree Gateway provide some request mapper middlewares for common tasks already included in its distribution. Check the list here.