simple-proxy-gateway

1.0.1 • Public • Published

Simple Proxy Gateway

This app is meant to be a very simple proxy gateway for API's, that is run alongside another node app or micro-service(s).

Requirements

  • NodeJS 6.x
  • Redis
  • Your own API's from somewhere

Getting Started

To get the app up and running quick:

Using Docker Compose

  1. Clone this repo
  2. Run docker-compose up
  3. Visit http://localhost:3000/posts?apikey=LeCxzc9yRJoBRBgpGjNCsqCaVdNNiQdezNwGcNEp

Running it like a normal NodeJS app

  1. npm install simple-proxy-gateway --save
  2. Start up a Redis server and point the app to it (see Env. Vars section below for more information). Or, for testing real quick: docker run -p 6379:6379 redis.
  3. Configure the app via env vars or provide a config with your site info (See below for more on the config section).

Sample App:

var Gateway = require('simple-proxy-gateway');
 
var gateway = new Gateway(require('./config'));
var port = process.env.PORT || 8001;
 
gateway.start(port, () => {
    logger.info('Gateway listening on port ' + port);
});
  1. node .

Configuration

There are two ways to configure the gateway: 1) Via a config file or 2) Via ENV vars.

Config File

sites: An array of sites the gateway will proxy

Sample site configuration (You can look at the config.js sample file in this repo as well):

{
    /**
     * Express route to expose on the gateway for this site.
     * The example below will allow any endpoint after `/`. e.g. `/posts`
     */
    route: '/*',
    /**
     * The site name.  This is checked against the consumer's access to a site.
     */
    site: 'jsonplaceholder.typicode.com',
    /**
     * The target server that the gateway is proxying.
     */
    upstreamUrl: 'https://jsonplaceholder.typicode.com',
    /**
     * The options for the gateway proxy.  This app uses the `express-http-proxy` module and will pass these options to this module.
     */
    options: {
        https: true
    },
    /**
     * The authentication plugin and options to assign to this site.
     * Auth plugins can be found in the /auth folder
     */
    auth: {
        type: 'apikey',
    },
    /**
     * List of middleware plugins to apply to this site.  Plugins can be found
     * in the /plugins folder
     */
    plugins: [
        { type: 'siteAccess' },
        { type: 'rateLimit', lookup: 'user.apikey' }
    ]
}

consumers: An array of consumers the gateway will allow through

Sample consumer:

{
    /**
     * Consumer name
     */
    name: 'some-app-from-somebody',
    /**
     * API key used by this consumer (used by the apikey auth plugin)
     */
    apikey: '123456789abcdefghijklmnop',
    /**
     * Rate limit settings for this consumer (used by the rateLimit plugin)
     */
    rateLimit: {
        total: 10000000,
        expire: 1000 * 600 * 60,
    },
    /**
     * The site name this consumer can access.  Used by the siteAccess plugin
     * to check against the site name to see if this consumer can hit the site.
     */
    site: 'jsonplaceholder.typicode.com'
}

Environment Variables

You can also configure the gateway to proxy / secure one site using env vars:

  • PORT: The port on which the gateway runs
  • REDIS_HOST: Hostname of the redis server
  • REDIS_PORT: The redis port the server runs on
  • SITE_NAME: The site name
  • SITE_ENDPOINT_PATH: The express route / path to expose on the gateway. e.g. /* to catch everything.
  • SITE_UPSTREAM_URL: The upstream site the gateway is proxying
  • SITE_HTTPS: Use https for the proxy
  • SITE_AUTH_TYPE: The auth plugin to use. e.g. apikey
  • SITE_CONSUMER_APIKEY: The apikey of the consumer (if using the apikey plugin)
  • SITE_IS_RATE_LIMITED: Enable rate limiting
  • SITE_RATE_LIMIT_TOTAL: Total number of requests allowed
  • SITE_RATE_LIMIT_EXPIRATION: Timeframe in which number of requests are allowed
  • SITE_PLUGINS: Plugins to enable for the site. e.g. rateLimit, siteAccess
  • SITE_PLUGINS_RATE_LIMIT_LOOKUP: Path in the Express request object to compare to enforce the rate limit. e.g. user.apikey

Using a custom plugin

In a plugin's configuration (inside the site config), you can tell the gateway where your custom module is using the modulePath property:

// This object also gets passed to your custom plugin, for configuration
{
    type: 'mycustomplugin',
    modulePath: 'PATH_TO_PLUGIN_FOLDER/mycustomplugin',
    someParam: true,
    someOtherParam: '123456789'
}

Writing plugins

Authentication plugins are found in the auth folder, site plugins are found in the plugins folder.

All plugins must follow the following conventions:

  • The file name should be the name of the plugin. e.g. apikey.js means the name used in the config to select this plugin is apikey.
  • The plugin should export a ES6 class
  • The plugin should have a middleware method which returns an Express middleware function.

See below for example of the API key auth plugin:

var logger = require('winston');
 
class APIKeyAuthPlugin {
    constructor(config, server) {
        this.config = config;
    }
 
    middleware (site) {
        var consumers = this.config.consumers;
 
        return (req, res, next) => {
            var apiKey = req.headers.apikey || req.query.apikey;
            var consumer = consumers.filter(consumer => consumer.apikey && consumer.apikey === apiKey);
 
            // Make sure there is a consumer
            if (consumer.length < 1) {
                res.status(401).send({
                    message: 'Unauthorized'
                });
                logger.log('debug', 'Unauthorized', apiKey);
                return;
            } else {
                req.user = consumer[0];
            }
 
            return next();
        };
    }
}
 
module.exports = APIKeyAuthPlugin;
 

See below for example of the rate limiting plugin:

var logger = require('winston');
 
class RateLimitPlugin {
    constructor(config, pluginConfig, server) {
        this.config = config;
        this.pluginConfig = pluginConfig;
        this.limiter = require('express-limiter')(server.app, server.db);
    }
 
    middleware (site) {
        var lookup = process.env.SITE_PLUGINS_RATE_LIMIT_LOOKUP || this.pluginConfig.lookup;
 
        return this.limiter({
            method: 'all',
            lookup: function (req, res, opts, next) {
                var user = req.user;
 
                opts.lookup = lookup || 'user.apikey';
                opts.total = user.rateLimit.total;
                opts.expire = user.rateLimit.expire;
 
                return next();
            },
            onRateLimited: function (req, res) {
                res.status(429).send({
                    message: 'Rate limit exceeded'
                });
                logger.log('debug', 'Rate limit exceeded', req.user);
            }
        });
    }
}
 
module.exports = RateLimitPlugin;

Readme

Keywords

none

Package Sidebar

Install

npm i simple-proxy-gateway

Weekly Downloads

1

Version

1.0.1

License

Apache 2.0

Last publish

Collaborators

  • rblalock