rest-auto-router

Simple auto router for Node.js raw http designed for JSON RESTful API


Keywords
rest, api, rest api, restful, restful api, json, restful json api, auto router, auto route, web, server, web server, http, raw http, nodejs, node, node raw http, api-restfull, api-server, autoroute, npm-package
License
MIT
Install
npm install rest-auto-router@3.6.13

Documentation

nodejs-rest-auto-router

Simple auto router for Node.js raw http designed for JSON RESTful API, based on White House Web API Standards

npm package

npm install --save rest-auto-router

Expect to receive requests from reverse proxy only, not recommended to use without proxy server such as Nginx, Apache Httpd, HAProxy, etc.

Usage

// test and example purpouse only

const conf = {
  // path to routes folder
  'path': process.cwd() + '/routes/',
  // listened tcp port
  // should be opened for localhost only
  'port': 8080,
  // part of the URL to be deleted in routing
  // like RewriteBase of Apache Httpd mod_rewrite
  'base_uri': '/v1/',
  // must be configured in common with proxy server
  'proxy': {
    // request timeout in ms
    'timeout': 30000,
    // X-Authentication header
    'auth': 'proxypassword'
  },
  // default error messages
  // used when messages are null
  'error_messages': {
    'dev': 'Unknow error',
    'usr': {
      'en_us': 'Unexpected error, report to support or responsible developer',
      'pt_br': 'Erro inesperado, reportar ao suporte ou desenvolvedor responsável'
    }
  },
  // allow clients to specify what fields to receive from resource
  // if true, response should vary by http param 'fields'
  'vary_fields': false
}

var restAutoRouter = require('./main.js')
restAutoRouter(conf)

Routes

  • Files on routes path (conf.path) should always end with .js
  • Must export an object with available methods (HTTP verbs) for this API resource
  • Each object property (method) should be a function with params id, meta, body, respond
  • Files and directories started with . (dot) and # (hashtag) will be ignored

Route example

  1. Filename: products.js
  2. Route: products
  3. URL served: api.example.com/v1/products.json
  • In the above example conf.base_uri = '/v1/'
  • Works without .json extension too
function get (id, meta, body, respond, props) {
  if (id) {
    respond(id)
  } else {
    respond('Example')
  }
}

module.exports = {
  'GET': get
}

It's possible to define functions for GET, POST, PATCH, PUT and DELETE methods (HTTP verbs), OPTIONS will list available methods for the resource and other methods will return 405 status code.

Callback params

  • id (string) is the resource ID at URL
  • meta (object) is the metadata options defined by query string
    • limit (integer)
      • ?limit=100
      • meta.limit = 100
    • offset (integer)
      • ?offset=10
      • meta.offset = 10
    • sort (array)
      • ?sort=pop,-prc
      • meta.sort = [{ field: 'pop', order: 1 }, { field: 'prc', order: -1 }]
    • fields (array)
      • ?fields=id,price
      • meta.fields = [ 'id', 'price' ]
    • query (object)
      • ?any=1&other=2
  • body (mixed) is the received request body
    • Body must be a valid JSON
    • Will be ignored on GET, DELETE and OPTIONS requests
  • respond (function) is the function to respond the HTTP request
    • Function params:
      • obj (mixed)
      • meta (object)
      • status (integer) default = 200
      • errorCode (integer, string) default = -1
      • devMsg (string) default = null
      • usrMsg (string, object) default = null
      • moreInfo (string) default = null
  • props (array) is the list of other IDs (properties, subresource IDs...) at URL

Eg.: /{resource}/{id}/{subresource}/{props[0]}.json?limit=100&offset=10&sort=pop,-prc&fields=id,price&any=1&other=2

Middleware

You can specify a function to be called before route:

restAutoRouter(conf, middleware)

And a Console object (to log):

restAutoRouter(conf, middleware, logger)

Middleware example:

function middleware (id, meta, body, respond, req, res, resource, verb, endpoint) {
  // function called before endpoints
  // authentications and other prerequisites when necessary
  // logger.log(resource)
  if (typeof req.headers['x-real-ip'] === 'string') {
    let ip = req.headers['x-real-ip']
    let auth

    if (ip === '127.0.0.1') {
      // localhost authentication
      // all granted
      auth = true
    } else {
      // continue without authentication
      auth = false
    }

    // pass auth token header
    endpoint(id, meta, body, respond, auth, ip, req.headers['x-token'])
  } else {
    respond({}, null, 403, 100, 'Who are you? Unknown IP address')
  }
}