Skip to content

djensen47/seneca-web

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Seneca

seneca-web

npm version Build Status Coverage Status Dependency Status Gitter chat

  • Sponsor: nearForm
  • Node: 4.x, 6.x
  • Seneca: 1.x - 3.x

This plugin allows http requests to be mapped to seneca actions. Http actions handled locally can access the raw request and response objects. Actions handled over transport can access a reduced set of request data including payloads and headers.

If you're using this module, and need help, you can:

If you are new to Seneca in general, please take a look at senecajs.org. We have everything from tutorials to sample apps to help get you up and running quickly.

Install

npm install seneca-web

Test

To run tests locally,

npm run test

To obtain a coverage report,

npm run coverage; open docs/coverage.html

Quick example

Route map

var Routes = [{
  pin: 'role:admin,cmd:*',
  prefix: '/v1',
  postfix: '/?param=true'
  map: {
    home: {
      GET: true,
      POST: true,
      alias: '/home'
    },
    logout: {
      GET: true,
      redirect: '/'
    },
    profile: {
      GET: true,
      autoreply: false
    },
    login: {
      POST: true,
      auth: {
        strategy: 'local',
        pass: '/profile',
        fail: '/'
      }
    }
  }
}]

Adapters

An adapter that maps the routes to routes in a web framework must be provided via the adapter parameter

The following adapters are provided:

Hapi

'use strict'

var Hapi = require('hapi')
var Seneca = require('seneca')
var Web = require('../../')
var Routes = require('./common/routes')
var Plugin = require('./common/plugin')

var config = {
  routes: Routes,
  adapter: require('seneca-web-adapter-hapi'),
  context: (() => {
    var server = new Hapi.Server()
    server.connection({port: 4000})
    return server
  })()
}

var seneca = Seneca()
  .use(Plugin)
  .use(Web, config)
  .ready(() => {
    var server = seneca.export('web/context')()

    server.start(() => {
      console.log('server started on: ' + server.info.uri)
    })
  })

Express

'use strict'

var Seneca = require('seneca')
var Express = require('Express')
var Web = require('../../')
var Routes = require('./common/routes')
var Plugin = require('./common/plugin')

var config = {
  routes: Routes,
  adapter: require('seneca-web-adapter-express'),
  context: Express()
}

var seneca = Seneca()
  .use(Plugin)
  .use(Web, config)
  .ready(() => {
    var server = seneca.export('web/context')()

    server.listen('4000', () => {
      console.log('server started on: 4000')
    })
  })

Connect

'use strict'

var Seneca = require('seneca')
var Connect = require('connect')
var Http = require('http')
var Web = require('../../')
var Routes = require('./common/routes')
var Plugin = require('./common/plugin')

var config = {
  routes: Routes,
  adapter: require('seneca-web-adapter-connect'),
  context: Connect()
}

var seneca = Seneca()
  .use(Plugin)
  .use(Web, config)
  .ready(() => {
    var connect = seneca.export('web/context')()
    var http = Http.createServer(connect)

    http.listen(4060, () => {
      console.log('server started on: 4060')
    })
  })

Action Patterns

role:web,route:*

Define a web service as a mapping from URL routes to action patterns.

seneca.act('role:web', {routes: Routes}, (err, reply) => {
  console.log(err || reply.routes)
})

Exported Methods

context

Provides the current context so it can be used to start the server or add custom logic, strategies, or middleware.

var seneca = Seneca()
  .use(Plugin)
  .use(Web, config)
  .ready(() => {

    // This will be whatever server is being used.
    // seneca-web doesn't autostart the server, it
    // must first be exported and then started.
    var context = seneca.export('web/context')()
  })

mapRoutes

Allows routes to be mapped outside of using seneca directly. Provides the same functionality as role:web,route:*.

var seneca = Seneca()
  .use(Plugin)
  .use(Web, config)
  .ready(() => {

    // Provides the same functionality as seneca.act('role:web', {routes ...})
    // can be used to add more routes at runtime without needing seneca.
    seneca.export('web/mapRoutes')(Routes, (err, reply) => {
      ...
    })
  })

setServer

Allows the server and adapter to be swapped out after runtime.

var seneca = Seneca()
  .use(Plugin)
  .use(Web, config)
  .ready(() => {

    var config = {
      context: Express(),
      adapter: require('seneca-web-adapter-express'),
      routes: Routes
    }

    // Provides the same functionality as seneca.act('role:web', {routes ...})
    // can be used to add more routes at runtime without needing seneca.
    seneca.export('web/setServer')(config, (err, reply) => {
      ...
    })
  })

Auth

Both Hapi and Express support secure routing. Hapi support is via it's built in auth mechanism and allows Bell and custom strategies. Express auth is provided via passport, which supports 100s of strategies.

Secure Express routes

map: {
  home: {
    GET: true,
    POST: true,
    alias: '/'
  },
  logout: {
    GET: true,
    redirect: '/'
  },
  profile: {
    GET: true,
    secure: {
      fail: '/'
    }
  },
  login: {
    POST: true,
    auth: {
      strategy: 'local',
      pass: '/profile',
      fail: '/'
    }
  }

Express routes use auth for passport.authorize and secure for checking the existence of request.user. Both secure and auth guards support fail redirects. Auth also supports pass routing.

Secure Hapi routes

map: {
  home: {
    GET: true,
    POST: true,
    alias: '/'
  },
  profile: {
    GET: true,
    auth: {
      strategy: 'simple',
      fail: '/'
    }
  },
  admin: {
    GET: true,
    auth: {
      strategy: 'simple',
      pass: '/profile',
      fail: '/'
    }
  }
}

Hapi routes do not use the secure option. All routes are secured using auth. Both pass and fail redirects are supported.

Body Parser

If a body parser has not been provided using express or connect, seneca-web will attempt to parse the body. This will not work if a body-parser has already been defined for the app. To disable this behavior, pass {options: {parseBody: false}} to the plugin options.

Examples

A number of examples showing basic and secure usage for hapi and express as well as showing connect and log usage are provided in ./docs/examples. Examples include,

  • Logging routes when building maps (via log adapter).
  • Basic expres, hapi, and connect usage.
  • Securing Express and Hapi routes.
  • Proxying some routes over to transport

Contributing

The Senecajs org encourage open participation. If you feel you can help in any way, be it with documentation, examples, extra testing, or new features please get in touch.

License

Copyright (c) 2013 - 2016, Richard Rodger and other contributors. Licensed under MIT.

About

Http route mapping for Seneca microservices.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • JavaScript 100.0%