moleculer-web
The moleculer-web is the official API gateway service for Moleculer framework. Use it to publish your services as RESTful APIs.
Features
- support HTTP & HTTPS
- serve static files
- multiple routes
- support Connect-like middlewares in global-level, route-level and alias-level.
- alias names (with named parameters & REST routes)
- whitelist
- multiple body parsers (json, urlencoded)
- CORS headers
- Rate limiter
- before & after call hooks
- Buffer & Stream handling
- middleware mode (use as a middleware with Express)
Try it in your browser!
Install
npm i moleculer-web |
Usage
Run with default settings
This example uses API Gateway service with default settings.
You can access all services (including internal $node.
) via http://localhost:3000/
const { ServiceBroker } = require("moleculer"); |
Example URLs:
Call
test.hello
action:http://localhost:3000/test/hello
Call
math.add
action with params:http://localhost:3000/math/add?a=25&b=13
Get health info of node:
http://localhost:3000/~node/health
List all actions:
http://localhost:3000/~node/actions
Whitelist
If you don’t want to publish all actions, you can filter them with whitelist option.
Use match strings or regexp in list. To enable all actions, use "**"
item.
broker.createService({ |
Aliases
You can use alias names instead of action names. You can also specify the method. Otherwise it will handle every method types.
Using named parameters in aliases is possible. Named parameters are defined by prefixing a colon to the parameter name (:name
).
broker.createService({ |
The named parameter is handled with path-to-regexp module. Therefore you can use optional and repeated parameters, as well.
Aliases ActionThe API gateway implements
listAliases
action that lists the HTTP endpoints to actions mappings.
You can also create RESTful APIs.
broker.createService({ |
For REST routes you can also use this simple shorthand alias:
broker.createService({ |
To use this shorthand alias, create a service which has
list
,get
,create
,update
andremove
actions.
You can make use of custom functions within the declaration of aliases. In this case, the handler’s signature is function (req, res) {...}
.
Please note that Moleculer uses native Node.js HTTP server
broker.createService({ |
There are some internal pointer in
req
&res
objects:
req.$ctx
are pointed to request context.req.$service
&res.$service
are pointed to this service instance.req.$route
&res.$route
are pointed to the resolved route definition.req.$params
is pointed to the resolved parameters (from query string & post body)req.$alias
is pointed to the resolved alias definition.req.$action
is pointed to the resolved action.req.$endpoint
is pointed to the resolved action endpoint.req.$next
is pointed to thenext()
handler if the request comes from ExpressJS.E.g.: To access the broker, use
req.$service.broker
.
Mapping policy
The route
has a mappingPolicy
property to handle routes without aliases.
Available options:
all
- enable to request all routes with or without aliases (default)restrict
- enable to request only the routes with aliases.
broker.createService({ |
You can’t request the /math.add
or /math/add
URLs, only POST /add
.
File upload aliases
API Gateway has implemented file uploads. You can upload files as a multipart form data (thanks to busboy library) or as a raw request body. In both cases, the file is transferred to an action as a Stream
. In multipart form data mode you can upload multiple files, as well.
Example
const ApiGateway = require("moleculer-web"); |
Multipart parameters
In order to access the files passed by multipart-form these specific fields can be used inside the action:
ctx.params
is the Readable stream containing the file passed to the endpointctx.meta.$params
parameters from URL querystringctx.meta.$multipart
contains the additional text form-data fields must be sent before other files fields.
Auto-alias
The auto-alias feature allows you to declare your route alias directly in your services. The gateway will dynamically build the full routes from service schema.
Gateway will regenerate the routes every time a service joins or leaves the network.
Use whitelist
parameter to specify services that the Gateway should track and build the routes.
Example
// api.service.js |
// posts.service.js |
The generated aliases
GET /api/hi => test.hello |
Service level rest parameters
- fullPath, override all the path generated with a new custom one
- basePath, path to the service, by default is the one declared in
settings.rest
- path, path to the action
- method, method used to access the action
path is appended after the basePath
The combination path+basePath it’s not the same as using fullPath. For example:
// posts.service.js |
Will create those endpoints:
GET /tags |
fullPath ignores that prefix applied in the API gateway!
The rest param can be also be an array with elements with same structure discussed before. The can be applied both on settings and action level.
For example:
// posts.service.js |
Produce those endpoints
GET /api/my/awesome/posts/:id/ => posts.get |
Parameters
API gateway collects parameters from URL querystring, request params & request body and merges them. The results is placed to the req.$params
.
Disable merging
To disable parameter merging set mergeParams: false
in route settings. In this case the parameters is separated.
Example
broker.createService({ |
Un-merged req.$params
:
{ |
Query string parameters
More information: https://github.com/ljharb/qs
Array parameters
URL: GET /api/opt-test?a=1&a=2
a: ["1", "2"] |
Nested objects & arrays
URL: GET /api/opt-test?foo[bar]=a&foo[bar]=b&foo[baz]=c
foo: { |
Middlewares
It supports Connect-like middlewares in global-level, route-level & alias-level. Signature: function(req, res, next) {...}
. For more info check express middleware
Examples
broker.createService({ |
Use swagger-stats UI for quick look on the “health” of your API (TypeScript)
import { Service, ServiceSchema } from "moleculer"; |
Error-handler middleware
There is support to use error-handler middlewares in the API Gateway. So if you pass an Error
to the next(err)
function, it will call error handler middlewares which have signature as (err, req, res, next)
.
broker.createService({ |
Serve static files
It serves assets with the serve-static module like ExpressJS.
broker.createService({ |
Calling options
The route
has a callOptions
property which is passed to broker.call
. So you can set timeout
, retries
or fallbackResponse
options for routes. Read more about calling options
Please note that you can also set the timeout for an action directly in its definition
broker.createService({ |
Multiple routes
You can create multiple routes with different prefix, whitelist, alias, calling options & authorization.
When using multiple routes you should explicitly set the body parser(s) for each route.
broker.createService({ |
Response type & status code
When the response is received from an action handler, the API gateway detects the type of response and set the Content-Type
in the res
headers. The status code is 200
by default. Of course you can overwrite these values, moreover, you can define custom response headers, too.
To define response headers & status code use ctx.meta
fields:
Available meta fields:
ctx.meta.$statusCode
- setres.statusCode
.ctx.meta.$statusMessage
- setres.statusMessage
.ctx.meta.$responseType
- setContent-Type
in header.ctx.meta.$responseHeaders
- set all keys in header.ctx.meta.$location
- setLocation
key in header for redirects.
Example
module.exports = { |
Authorization
You can implement authorization. Do 2 things to enable it.
- Set
authorization: true
in your routes - Define the
authorize
method in service.
Example authorization
const E = require("moleculer-web").Errors; |
You can find a more detailed role-based JWT authorization example in full example.
Authentication
To enable the support for authentication, you need to do something similar to what is describe in the Authorization paragraph. Also in this case you have to:
- Set
authentication: true
in your routes - Define your custom
authenticate
method in your service
The returned value will be set to the ctx.meta.user
property. You can use it in your actions to get the logged in user entity.
Example authentication
broker.createService({ |
Route hooks
The route
has before & after call hooks. You can use it to set ctx.meta
, access req.headers
or modify the response data
.
broker.createService({ |
In previous versions of Moleculer Web, you couldn’t manipulate the
data
inonAfterCall
. Now you can, but you must always return the new or originaldata
.
Error handlers
You can add route-level & global-level custom error handlers.
In handlers, you must call the
res.end
. Otherwise, the request is unhandled.
broker.createService({ |
Error formatter
API gateway implements a helper function that formats the error. You can use it to filter out the unnecessary data.
broker.createService({ |
CORS headers
You can use CORS headers in Moleculer-Web service.
Usage
const svc = broker.createService({ |
Rate limiter
The Moleculer-Web has a built-in rate limiter with a memory store.
Usage
const svc = broker.createService({ |
Custom Store example
class CustomStore { |
ETag
The etag
option value can be false
, true
, weak
, strong
, or a custom Function
. For full details check the code.
const ApiGateway = require("moleculer-web"); |
Custom etag
Function
module.exports = { |
Please note, it doesn’t work with stream responses. In this case, you should generate the etag
by yourself.
Custom etag
for streaming
module.exports = { |
HTTP2 Server
API Gateway provides an experimental support for HTTP2. You can turn it on with http2: true
in service settings.
Example
const ApiGateway = require("moleculer-web"); |
ExpressJS middleware usage
You can use Moleculer-Web as a middleware in an ExpressJS application.
Usage
const svc = broker.createService({ |
Full service settings
List of all settings of Moleculer Web service:
settings: { |
Service Methods
addRoute
This service method (this.addRoute(opts, toBottom = true)
) add/replace a route. For example, you can call it from your mixins to define new routes (e.g. swagger route, graphql route, etc.).
Please note that if a route already exists this method will replace previous route configuration with a new one.
removeRoute
Service method removes the route by path (this.removeRoute("/admin")
).
Examples
-
- simple gateway with default settings.
-
- open HTTPS server
- whitelist handling
-
- serve static files from the
assets
folder - whitelist
- aliases
- multiple body-parsers
- serve static files from the
-
- simple authorization demo
- set the authorized user to
Context.meta
-
- simple server with RESTful aliases
- example
posts
service with CRUD actions
-
- webserver with Express
- use moleculer-web as a middleware
-
- start socket.io websocket server
- call action and send back the response via websocket
- send Moleculer events to the browser via websocket
-
- SSL
- static files
- middlewares
- multiple routes with different roles
- role-based authorization with JWT
- whitelist
- aliases with named params
- multiple body-parsers
- before & after hooks
- metrics, statistics & validation from Moleculer
- custom error handlers
-
- Webpack development environment for client-side developing
- webpack config file
- compression
- static file serving
-
- Webpack+Vue development environment for VueJS client developing
- webpack config file
- Hot-replacement
- Babel, SASS, SCSS, Vue SFC