Gathering detailed insights and metrics for moleculer-web-uws
Gathering detailed insights and metrics for moleculer-web-uws
npm install moleculer-web-uws
Typescript
Module System
Min. Node Version
Node Version
NPM Version
JavaScript (100%)
Verify real, reachable, and deliverable emails with instant MX records, SMTP checks, and disposable email detection.
Total Downloads
2,417
Last Day
1
Last Week
1
Last Month
7
Last Year
240
MIT License
12 Stars
26 Commits
3 Forks
3 Watchers
1 Branches
1 Contributors
Updated on Sep 17, 2024
Minified
Minified + Gzipped
Latest Version
0.1.1
Package Id
moleculer-web-uws@0.1.1
Unpacked Size
70.78 kB
Size
18.79 kB
File Count
16
NPM Version
7.11.2
Node Version
16.3.0
Cumulative downloads
Total Downloads
Last Day
0%
1
Compared to previous day
Last Week
0%
1
Compared to previous week
Last Month
-84.8%
7
Compared to previous month
Last Year
-67.3%
240
Compared to previous year
The moleculer-web-uws
is a fast API gateway service for Moleculer based on µWebSockets.js server. Use it to publish your services over HTTP and WebSockets.
1npm install moleculer-web-uws --save
This example uses the API Gateway service with default settings.
You can access all services (internal services not included) via http://localhost:3000/
1let { ServiceBroker } = require('moleculer');
2let ApiGateway = require('moleculer-web-uws');
3
4let broker = new ServiceBroker({ logger: console });
5
6// Create a service
7broker.createService({
8 name: 'test',
9
10 actions: {
11 hello: {
12 rest: 'GET /hello',
13
14 handler(ctx) {
15 return 'Hello API Gateway!'
16 }
17 }
18 }
19});
20
21// Load API Gateway
22broker.createService(ApiGateway);
23
24// Start server
25broker.start();
Test URLs:
Call
test.hello
action:http://localhost:3000/test/hello
You define a HTTP route in the action definition of your service using the rest property.
1broker.createService({
2 name: 'test',
3
4 actions: {
5 hello: {
6 // Define your route
7 rest: 'GET /hello',
8
9 handler(ctx) {
10 return 'Hello API Gateway!'
11 }
12 }
13 }
14});
You can also use the shorthand definition, in which the HTTP method is resolved to GET
1broker.createService({
2 name: 'test',
3
4 actions: {
5 hello: {
6 // Call this action with `GET /test/hello`
7 rest: '/hello',
8
9 handler(ctx) {
10 ...
11 }
12 }
13 }
14});
The route's url is resolved to /service-name/route-path
The service-name
is the value passed to rest parameter in the schema settings object definition of your service or
if no value is passed, the service-name is resolved to the specified name
of your service. This is to avoid any collisions with other service's routes.
1broker.createService({
2 name: 'test',
3
4 settings: {
5 // this becomes the service-name if defined
6 rest: 'alttest'
7 }
8
9 actions: {
10 hello: {
11 rest: '/hello',
12
13 handler(ctx) {
14 ...
15 }
16 }
17 }
18});
The route-path
is the value passed to rest parameter in the schema settings object definition of your service or
if no value is passed, the service-name is resolved to the specified name
of your service. This is to avoid any collisions with other service's routes.
You can use CORS headers in the api gateway service
1broker.createService({ 2 name: 'apigateway', 3 4 mixins: [APIGateway], 5 6 settings: { 7 // Global CORS settings for all routes 8 cors: { 9 // Configures the Access-Control-Allow-Origin CORS header. 10 origin: '*', // Can be an array of origins 11 // Configures the Access-Control-Allow-Methods CORS header. 12 methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'DELETE'], 13 // Configures the Access-Control-Allow-Headers CORS header. 14 allowedHeaders: [], 15 // Configures the Access-Control-Expose-Headers CORS header. 16 exposedHeaders: [], 17 // Configures the Access-Control-Allow-Credentials CORS header. 18 credentials: false, 19 // Configures the Access-Control-Max-Age CORS header. 20 maxAge: 3600 21 }, 22 } 23});
You can also use Route specific CORS settings (overwrites global settings)
1broker.createService({
2 name: 'test',
3
4 actions: {
5 hello: {
6 rest: {
7 path: '/routewithcors',
8 cors: {
9 origin: ['http://localhost:3000', 'https://localhost:4000'],
10 methods: ['GET'],
11 credentials: true
12 },
13 },
14
15 handler(ctx) {
16 ...
17 }
18 }
19 }
20});
The Api Gateway implements json
, urlencoded
, text
and multipart
(File Uploading) by default.
Only one of these can be used per route. To use a body-parser, you must add it to the rest definition.
1broker.createService({
2 name: 'test',
3
4 actions: {
5 hello: {
6 rest: 'GET json /hello', // Valid body-parsers are; json, urlencoded, text, multipart
7
8 params: {
9 name: 'string' // This should be passed in json format
10 }
11
12 handler(ctx) {
13 const { name } = ctx.params;
14 ...
15 }
16 }
17 }
18});
Please note, the parsed body is accessible through ctx.params as an object with named properties as defined by the client.
To use a named parameter, define it in the form route-path/:parametername
. The parameter is accessed through ctx.params
where the parametername is the property name.
1broker.createService({
2 name: 'test',
3
4 actions: {
5 hello: {
6 rest: 'GET /hello/:name',
7
8 handler(ctx) {
9 const { name } = ctx.params;
10 ...
11 }
12 }
13 }
14});
You can also use multiple named parameters as follows.
1broker.createService({
2 name: 'test',
3
4 actions: {
5 hello: {
6 rest: 'GET /hello/:name/:age',
7
8 handler(ctx) {
9 const { name, age } = ctx.params;
10 ...
11 }
12 }
13 }
14});
To implement authorization. Do 2 things to enable it.
authorize: true
in your routesauthorize
action in the api gateway service.The returned value will be set to the ctx.meta.authz
property. You can use it in your actions to get the authorized user entity.
1broker.createService({
2 name: 'test',
3
4 actions: {
5 hello: {
6 rest: {
7 path: 'GET /hello',
8
9 // First thing
10 authorize: true
11 },
12
13 handler(ctx) {
14 const { id, username, name } = ctx.meta.authz;
15 ...
16 }
17 }
18 }
19});
1let ApiGateway = require('moleculer-web-uws'); 2const { UnAuthorisedError } = require('moleculer-web').Errors; 3 4broker.createService({ 5 name: 'apigateway', 6 7 mixins: [APIGateway], 8 9 settings: { 10 ... 11 }, 12 13 actions: { 14 // Second thing 15 async authorize(ctx) { 16 const { req, res } = ctx.params; 17 // Define your authorization logic, like calling an auth service like so 18 let tokenId; 19 20 if (req.headers.authorization) { 21 const parts = req.headers.authorization.split(' '); 22 if (parts[0]/** type */ === 'Bearer') tokenId = parts[1]; 23 } 24 25 if (tokenId === '12345') { 26 // Ensure that that you return every information you might need later in 27 // your service's action so that you can access them as ctx.meta.authz 28 return { id: 1, username: 'john.doe', name: 'John Doe' }; 29 } 30 31 throw new UnAuthorizedError('Token Id not detected'); 32 } 33 } 34});
Please note that the module will not throw an UnAuthorizedError on your behalf. You have to throw it yourself if authorization fails.
To enable authentication, you need to do something similar to what is describe in the Authorization paragraph. Also in this case you have to:
authenticate
action in the api gateway serviceThe returned value will be set to the ctx.meta.auth
property. You can use it in your actions to get the logged in user entity.
1broker.createService({
2 name: 'test',
3
4 actions: {
5 hello: {
6 rest: {
7 path: 'GET /hello',
8
9 // First thing
10 authenticate: true
11 },
12
13 handler(ctx) {
14 const { id, username, name } = ctx.meta.auth;
15 ...
16 }
17 }
18 }
19});
1let ApiGateway = require('moleculer-web-uws'); 2 3broker.createService({ 4 name: 'apigateway', 5 6 mixins: [APIGateway], 7 8 settings: { 9 ... 10 }, 11 12 actions: { 13 // Second thing 14 async authentication(ctx) { 15 const { req, res } = ctx.params; 16 let accessToken = req.query['access_token']; 17 18 if (accessToken) { 19 if (accessToken === '12345') { 20 // valid credentials. It will be set to `ctx.meta.auth` 21 return { id: 1, username: 'john.doe', name: 'John Doe' }; 22 } 23 24 // invalid credentials 25 throw new Error('Could not login user!'); 26 } else { 27 // anonymous user 28 return null; 29 } 30 } 31 } 32});
To upload a file(s), use the multipart
property and no other body-parser should should be defined on the same action.
1broker.createService({
2 name: 'test',
3
4 actions: {
5 hello: {
6 rest: {
7 path: 'POST /upload',
8
9 multipart: {
10 fileSize: 100000, // Size in bytes that should not be exceeded
11
12 files: 1, // Number of files expected
13
14 fields: 3, // Number of fields that should not be exceeded.
15
16 onFileSizeLimit: (sizeOfReceivedFile, sizeExpected) => {
17 ...
18 },
19
20 onFieldsLimit: (numFieldsReceived, numFieldsExpected) => {
21 ...
22 },
23
24 onFilesLimit: (numFilesReceived, numFilesExpected) => {
25 ...
26 }
27 }
28 },
29
30 handler(ctx) {
31 // ctx.param will be an object of the form {fieldname, data, type, filename} or an array of
32 // such objects if more than 1 file is received.
33 const files = ctx.params;
34 const { fieldname, data, type, filename, size } = file;
35
36 // The fields are passed as an array of the form [fieldname => value]
37 const fields = ctx.meta.$multipart;
38
39 // Do something with the received file(s) and field(s)
40 ...
41 }
42 }
43 }
44});
Please note, the
data
property is a ReadableStream of the file data hence should be handled as a stream.
A global multipart options can be defined in the API Gateway as follows.
1let ApiGateway = require('moleculer-web-uws');
2
3broker.createService({
4 name: 'apigateway',
5
6 mixins: [APIGateway],
7
8 settings: {
9 multipart: {
10 fileSize: 100000, // Size in bytes, that should not be exceeded
11
12 files: 1, // Number of files expected
13
14 fields: 3, // Number of fields that should not be exceeded.
15
16 onFileSizeLimit: (size, sizeExpected) => {
17 ...
18 },
19
20 onFieldsLimit: (numFields, numFieldsExpected) => {
21 ...
22 },
23
24 onFilesLimit: (numFiles, numFilesExpected) => {
25 ...
26 }
27 }
28 }
29});
You can use the shorthand definition where multipart
is passed as the body-parser. The multipart settings defined in the API Gateway will be used instead.
1broker.createService({
2 name: 'test',
3
4 actions: {
5 hello: {
6 rest: 'POST multipart /upload',
7
8 handler(ctx) {
9 ...
10 }
11 }
12 }
13});
To access static files, define static settings in the API Gateway.
1let ApiGateway = require('moleculer-web-uws');
2
3broker.createService({
4 name: 'apigateway',
5
6 mixins: [APIGateway],
7
8 settings: {
9 static: {
10 // The url through which the file will be accessible as `/assets/:filename.ext`
11 rest: '/assets',
12
13 // Path to the directory where the files are stored
14 folder: '/assets',
15
16 // Defaults to false
17 cache: true,
18
19 // Custom headers to pass to response headers
20 // Optional
21 headers: {},
22
23 // Defaults to false
24 etag: true,
25 }
26 }
27});
The Static File server
is published as a separate service.
Service actions with the rest property in their definition are whitelisted by default. If the rest property is not defined or the service action's visibility is not public, it'll not be whitelisted to be accessed through the API Gateway.
Please note, routes are not defined within the API Gateway, but within the action definition of your service's schema.
To use WebSockets, ws
setting must be defined in the API Gateway as follows.
1let ApiGateway = require('moleculer-web-uws');
2
3broker.createService({
4 name: 'apigateway',
5
6 mixins: [ApiGateway],
7
8 settings: {
9 ws: {
10 path: '/*',
11
12 compression: 0,
13
14 idleTimeout: 0,
15
16 maxBackPressure: 1024 * 1024,
17
18 maxPayloadLength: 16 * 1024,
19
20 keepAlive: {
21 // Amount of seconds after which a PING message is sent to the client
22 interval: 5000,
23
24 // The message to be sent as a PING to the WebSocket client.
25 // Can be any value, as long as the client will be able to identify it as a PING control message
26 // from the server.
27 ping: new Uint8Array([50]),
28
29 // The message to be received from the WebSocket client as a PONG control message.
30 // Can be a Uint8Array or integer(Will be converted to TypedArray)
31 pong: new Uint8Array([50]),
32 },
33
34 upgrade: (res, req, context) => {
35 ...
36 },
37
38 open: (socket) => {
39 ...
40 },
41
42 message: async (app, socket, message, isBinary, topic) => {
43 ...
44 }
45 },
46 }
47});
The path
property MUST be passed. It is the url over which the WebSocket Connection is upgraded.
The rest of the properties are optional. If not defined, the are resolved to their default values.
What permessage-deflate compression to use. Can be DISABLED
, SHARED_COMPRESSOR
or any of DEDICATED_COMPRESSOR_xxxKB
. Defaults to SHARED_COMPRESSOR
. Read more at uWebSockets.js
Maximum amount of seconds that may pass without sending or getting a message. Connection is closed if this timeout passes. Disable by using 0. Defaults to 120. Read more at uWebSockets.js
Maximum length of allowed backpressure per socket when publishing or sending messages. Defaults to 1024 * 1024. Read more at uWebSockets.js
Maximum length of received message. If a client tries to send a message larger than this, the connection is immediately closed. Defaults to 16 * 1024. Read more at uWebSockets.js
You can also whitelist an action to be accessed over WebSockets by including the ws
property in its definition.
The action is routed through a PUB/SUB protocol in which the WebSocket client specifies the topic to publish the message to.
If this topic is matched, the received message from the client is passed to the action as ctx.params
.
1broker.createService({
2 name: 'test',
3
4 actions: {
5 draw: {
6 ws: {
7 // If not defined, the topic is resolved to `service-name/action-name`
8 topic: 'tool/draw',
9
10 // The result of this action will be published to all clients subscibed to this topic.
11 // Optional
12 publish: true,
13
14 // The result of this action will be sent to the client who sent the message
15 // Optional
16 send: true,
17
18 // If defined and is a callback, a client will only be subscribed to the topic if the callback returns true.
19 // Optional
20 condition: false // Should return a truthy result
21 },
22
23 handler(ctx) {
24 const message = ctx.params;
25 const connectionContext = ctx.meta.c_ctx;
26 ...
27 // Do something with the message and return the results(Optional)
28 }
29 }
30 }
31})
moleculer-web-uws is available under the MIT license.
Copyright (c) 2021 Jimmie Lovell
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
license file detected
Details
Reason
2 existing vulnerabilities detected
Details
Reason
Found 0/22 approved changesets -- score normalized to 0
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
branch protection not enabled on development/release branches
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Score
Last Scanned on 2025-03-10
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More