0.3.7 • Published 3 years ago

rest-express-wrapper v0.3.7

Weekly downloads
-
License
MIT
Repository
github
Last release
3 years ago

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 KeyDescriptionRequired
endpointsArray of endpoints (see structure below)x
limiterObject containing limiter database and any options
expressAppExpress Application (new Express())x
additionalLimiterOptionsAdditional limiter options (see options)
validateRequestCustom function used for request validation
getLimiterIdentifierCustom function used to set identifier used for limiter

Constructor limiter object

Object KeyDescriptionRequired
mongoClientMongo database db object
limiterOptionsrate limiter options relevant to the type of database passed

Endpoint structure

Endpoints contain the following

Object KeyDescriptionExample dataRequired
nameName of endpointloginx
disabledDisable the endpoint (not callable)true
pathREST pathloginx
defaultPathREST path prefixauthx
limiterLimiter objecttrue
typeRequest typeGETx
headersRequired headers'clientid'
bodyRequire body (requires body in JSON format)*'id', 'name'
executeFunction executed on endpoint reachedexecute(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 KeyDescriptionExample dataRequired
pointsHits allowed before limit enforced5x
durationTime before points are reset'2h'x
keyPrefixkey used to identifer limiter in database'loginrx'
0.3.6

3 years ago

0.3.5

3 years ago

0.3.7

3 years ago

0.3.4

3 years ago

0.3.0

3 years ago

0.3.2

3 years ago

0.3.1

3 years ago

0.3.3

3 years ago

0.2.0

3 years ago

0.1.0

3 years ago

0.1.1

3 years ago

0.0.1

3 years ago