Node microservice module: init every module, create an express server, add the required routes (/, /ping & /routes) & module routes.
npm install --save @neo9/n9-node-micro
n9Micro([options]): Promise<{ app, server }>
Options:
- hasProxy:
Boolean
, default:true
, define if the server should handle JWT (see Authentication section below) - path:
String
, default:'./modules/'
- log:
Function
, default:global.log
, need to be a N9Log instance. If no one is found, will usen9Log('n9-node-micro')
- http:
Object
, default:{}
- logLevel:
String
|false
, default:'dev'
, see available levels - port:
Number
, default:5000
- preventListen:
Boolean
, default:false
- logLevel:
- jwt:
Object
, default:{ secret: 'secret', expiredIn: '7d' }
, only whenhasProxy: false
- secret:
String
, default'secret'
- expiredIn:
String
, default'7d'
- secret:
- prometheus
Object
, default:{}
- port:
Number
- labels?:
String[]
- getLabelValues?:
Function
- accuracies?:
String[]
- skip?:
Function
- port:
modules/
users/
users.init.ts
users.routes.ts
server.ts
server.ts
import n9Log from '@neo9/n9-node-log'
import n9Micro from '@neo9/n9-node-micro'
(async () => {
await n9Micro({ log: n9Log('my-app') })
})()
Every module can have a *.init.(ts|js)
file wich exports a method. This method can be asynchronous (using async
or returning a Promise
), it reveices an object as argument with log
, app
and server
.
Example:
modules/io/io.init.ts
export default
import * as socketIO from 'socket.io'
export default async function({ log, server }) {
log.info('Creating socket server')
global.io = socketIO(server)
}
Routes format (*.routes.ts
) should export an Array
of Object
with at least these properties:
- method:
String
or[String]
- path:
String
- handler:
Function
or[Function]
Optional properties:
- version:
String
or[String]
, default:'*'
- name:
String
, default:handler.name
, for n9-node-connector - validate:
Object
, default:{}
- options: See Express Validation Options, default:
- allowUnknownHeaders:
true
, - allowUnknownCookies:
true
- allowUnknownBody:
false
, - allowUnknownQuery:
false
, - allowUnknownParams:
true
,
- allowUnknownHeaders:
- headers: Joi Schema
- cookies: Joi Schema
- params: Joi Schema
- query: Joi Schema
- body: Joi Schema
- options: See Express Validation Options, default:
- session:
Boolean
orObject
, default:false
, see Authentication below for more informations. - can:
Object
, check imperium can middleware for usage - is:
Array<string>
|string
, check imperium is middleware - withAcl:
Boolean
default:false
, ask for acl actions to be injected to the response object. Check imperium for more information - documentation:
Object
, default:{}
- description:
String
- response:
Object
, example of response sent back
- description:
Example :
modules/foo/foo.routes.js
import * as Joi from 'joi'
export default [
{
version: 'v1',
method: 'post',
path: '/foo',
validate: {
body: Joi.object().keys({
foo: Joi.boolean()
})
},
documentation: {
description: 'Foo route',
response: { ok: true }
},
handler: (req, res) => {
res.json({ ok: true })
}
}
]
server.ts
import n9Micro from '@neo9/n9-node-micro'
(async () => {
await n9Micro()
})()
If we go to http://localhost:5000/routes, we will have:
[
{
module: 'foo',
name: 'handler',
description: 'Foo route',
version: 'v1',
method: 'post',
path: '/v1/foo',
session: false,
acl: [ ],
validate: {
body: {
type: 'object',
properties: {
foo: {
type: 'boolean'
}
},
additionalProperties: false,
patterns: [ ]
}
},
response: {
ok: true
}
}
]
Send back the application name (from package.json
).
Send back status code 200 with text pong
.
Send back the list of routes available for the microservice.
This module supports 2 ways for authentication, behind a proxy (n9-node-micro-proxy
) or alone, to choose which one you want to use, specify the hasProxy
option for n9Micro()
.
session
header:hasProxy: true
- JSON Web Token:
hasProxy: false
By default, hasProxy
is set to true
, this means that n9Micro
will load req.session
from the session header.
When defining the routes in your *.routes.ts
files, you can use the session
key to define the behaviour of n9Micro
.
- session:
Boolean
orObject
, default:false
- type:
String
, default:'require'
, values:'require'
or'load'
- getToken:
Function
, default:undefined
, called withreq
as argument and should returns the token to decode (only forhasProxy: false
)
- type:
When type
is 'load'
, n9Micro will try to load req.session
but will not fail.
By default, hasProxy
is true
, this means that n9Micro
will load req.session
from JSON.parse(req.headers.session)
.
req.headers.session
should be a JSON string and has a userId
property when parsed.
Only with hasProxy: false
n9Micro
supports JWT and will check the Authorization
header to be a valid token.
Think to give
jwt
option ton9Micro()
to give the secret key to sign & decode
Example:
// modules/users/users.routes.ts
export default [
{
method: 'post',
path: '/me',
session: true,
handler: function(req, res, next) {
res.json(req.session)
}
}
]
Here session: true
, will require req.headers.authorization
to exists (will use jwt
option given to n9Micro()
to decode).
The module also add 2 useful methods for loading a session & generating a JWT into req
:
req.generateJWT(session: Object): Promise<string>
Generates and returns a JWT based on the session
.
req.loadSession(getToken?: Function): Promise<void>
Will load the session from req
and add it to req.session
.
getToken
is optional, takes req
as argument and should returns the JWT (example: (req) => req.query.token
)
Example:
// Generate a new token for each authenticated request
app.use(async function (req, res, next) {
try {
await req.loadSession() // Add req.session
res.setHeader('new-token', await req.generateJWT(req.session))
} catch (err) {
// Ignore err
}
})