seneca-web
v2.2.2
Published
Http route mapping for Seneca microservices.
Downloads
2,362
Readme
seneca-web
- 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:
- Post a github issue,
- Tweet to @senecajs,
- Ask on the Gitter.
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:
- seneca-web-adapter-connect
- seneca-web-adapter-express
- seneca-web-adapter-hapi
- seneca-web-adapter-koa1
- seneca-web-adapter-koa2
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')
})
})
Plugin Configuration
context
- optional. Routes are mapped to the context. You can provide this later by acting upon role:web,context:* or calling either the context, or setServer exported method.routes
- optional. An object identifying the routes to map. See Providing Routes for more details. You can add to this later acting upon role:web,route:* or calling the mapRoutes or setServer exported method.adapter
- optional. the adapter to use. See Adapters above for a list of supported web frameworks. You can add this later by calling the setServer exported method.auth
- optional. Authentication provider (express only). See Authentication for more detailsoptions
- optional. Additional optionsmiddleware
- object. default: null. Provide middleware functions that can be called prior the request handler.parseBody
- boolean. default: true. If a body parser has not been provided usingexpress
orconnect
,seneca-web
will attempt to parse the body. This will not work ifbody-parser
has already been used on the app. To disable this behavior, pass{options: {parseBody: false}}
to the plugin options.
.use(SenecaWeb, {
routes: Routes,
context: express,
adapter: require('seneca-web-adapter-express'),
auth: Passport,
options: {
parseBody: false,
middleware: {
'some-middleware': (req, res, next) => {
next()
}
}
}
})
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)
})
role:web,set:server
Change any of the plugin configuration options. Note that only plain objects are transported across microservices. In practice, this can only really be used on the same microservice node, or to set options
and routes
.
seneca.act('role:web,set:server', {
routes: Routes,
context: context,
adapter: require('seneca-web-adapter-express'),
auth: Passport,
options: {parseBody: false}
}, (err, reply) => {
console.log(err || reply.ok)
})
For the definition expected for Routes, see Providing 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) => {
...
})
})
For the definition expected for Routes, see Providing Routes
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.
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.