rest-express-wrapper
TypeScript icon, indicating that this package has built-in type declarations

0.3.7 • Public • Published

QuickExpress (rest-express-wrapper)

npm npm bundle size npm downloads

QuickExpress is an express wrapper created to initialise REST endpoints and validate all calls globally.

To utilise the rate limiting function, a mongo database object must provided. Support for alternatives will be added in due course (Redis, Memcache, mySQL & PostGres)

Flow Diagram

Setup

Creating endpoints

Without rate limiter

const endpoint: EndpointStruc = {
  name: 'TestEndpoint',
  path: 'testendpoint',
  defaultPath: 'path',
  type: 'GET',
  headers: ['text'],
  execute(
    req: express.Request,
    res: express.Response,
    headers: express.Headers
  ) {
    res.status(200).send(headers.text);
  },
};

With limiter:

const endpoint: EndpointStruc = {
  name: 'TestEndpoint',
  path: 'testendpoint',
  defaultPath: 'path',
  type: 'GET',
  headers: ['text'],
  limiter: {
    points: 10,
    duration: '1d', /* other examples: 500 (500 seconds), '1m' (60 seconds), '5m' (300 seconds), '10h' (36000 seconds), '1d' (86400 seconds) */
    keyPrefix: 'testlimiter' /* Name of table in database */
  }
  execute(
    req: express.Request,
    res: express.Response,
    headers: express.Headers
  ) {
    res.status(200).send(headers.text);
  },
};

Creating the express wrapper object

Without rate limiter:

const app = express();

const expressWrapper = new ExpressWrapper({
  endpoints,
  expressApp: app,
});

With rate limiter:

const { MongoClient } = require('mongodb');

const mongoOpts = {
  useNewUrlParser: true,
};

const mongoConn = MongoClient.connect('mongodb://localhost:27017', mongoOpts);

const app = express();

const expressWrapper = new ExpressWrapper({
  endpoints,
  expressApp: app,
  limiter: { mongoClient: mongoConn.db('rate_limiter_database_name') },
});

Initialise endpoints

Before endpoints can be reached, you must initialise them via:

expressWrapper.initialise();

Using custom validation

Validation request

You can pass a custom validation function that is applied when any endpoint is reached, this could include validating user logins/sessions or confirming the contents of specific headers.

The custom validation function accepts the following arguments as an object (typescript interface: 'ValidationRequest'):

{
  headers: express.Headers;
  body?: express.body;
  endpoint: EndpointStruc
}

And must return an object containing a boolean success key. Full response options:

{
  success: boolean;
  status?: number;
  error?: string;
  headers?: any;
}

Example of validation function utilising all possible return options.

Standard response:

const customValidator = ({
  headers,
  body,
  endpoint,
}: ValidationRequest): Promise<ValidationResponse> => {
  if (headers.clientid === process.env.CLIENT_ID) {
    return { success: true, headers: { userID: resp.userid } };
  } else {
    return {
      success: false,
      status: 401,
      error: 'Invalid client id provided, unauthorised',
    };
  }
};

As a promise:

const customValidator = ({
  headers,
  body,
  endpointName,
  endpointType,
}: ValidationRequest): Promise<ValidationResponse> =>
  new Promise((resolve) => {
    // Here checkLogin is a promise function used to validate an active session key
    checkLogin(headers.sessionkey).then((resp) => {
      if (resp.success) {
        resolve({ success: true, headers: { userID: resp.userid } });
      } else {
        resolve({
          success: false,
          status: 401,
          error: 'Invalid session key provided, unauthorised',
        });
      }
    });
  });

Limiter identifier

The identifier used in determining a request origin can be customised. By default, req.ip is used from the express request object but this is not always sufficient.

To pass a custom identifier, you can define a function similar to below:

const getLimiterIdentifier = (req: express.Request): string => {
  return req.headers['x-forwarded-for'] || req.socket.remoteAddress;
};

Constructor

To initialise the wrapper, the following must be passed

Object Key Description Required
endpoints Array of endpoints (see structure below) [x]
limiter Object containing limiter database and any options
expressApp Express Application (new Express()) [x]
additionalLimiterOptions Additional limiter options (see options)
validateRequest Custom function used for request validation
getLimiterIdentifier Custom function used to set identifier used for limiter

Constructor limiter object

Object Key Description Required
mongoClient Mongo database db object
limiterOptions rate limiter options relevant to the type of database passed

Endpoint structure

Endpoints contain the following

Object Key Description Example data Required
name Name of endpoint login [x]
disabled Disable the endpoint (not callable) true
path REST path login [x]
defaultPath REST path prefix auth [x]
limiter Limiter object true
type Request type GET [x]
headers Required headers ['clientid']
body Require body (requires body in JSON format)* ['id', 'name']
execute Function executed on endpoint reached execute(req,res,headers){} [x]

*Body requires either express.json() or bodyParser() middleware in order to access the JSON req.body (e.g. app.use(express.json()))

Limiter object

Note: In order to utilise the rate limiter, a valid database object must be passed to the constructor

Object Key Description Example data Required
points Hits allowed before limit enforced 5 [x]
duration Time before points are reset '2h' [x]
keyPrefix key used to identifer limiter in database 'loginrx'

Package Sidebar

Install

npm i rest-express-wrapper

Weekly Downloads

1

Version

0.3.7

License

MIT

Unpacked Size

41.6 kB

Total Files

27

Last publish

Collaborators

  • thorn_a