
Security News
Risky Biz Podcast: Making Reachability Analysis Work in Real-World Codebases
This episode explores the hard problem of reachability analysis, from static analysis limits to handling dynamic languages and massive dependency trees.
node-moleculer-web
Advanced tools
High-performance web server integration for Moleculer based on uWebSockets.js.
index.d.ts
.npm install node-moleculer-web
1 Create controller in folder controllers/home.js
const {AbstractController} = require('node-moleculer-web');
class HomeController extends AbstractController {
async index() {
return `helo world`;
}
}
module.exports = HomeController
2 Create service in folder services/app.service.js
const {UwsServer} = require('node-moleculer-web');
const {Service} = require('moleculer');
const HomeController = require('../controllers/home');
class AppService extends Service {
constructor(broker) {
super(broker);
this.parseServiceSchema({
name: 'app',
settings: {
// base port for server
port: process.evn.SERVER_PORT ?? 3101,
// on what ip to listen
ip: process.evn.SERVER_IP ?? '127.0.0.1',
portSchema: process.evn.SERVER_SCHEMA ?? 'node',
// if statics are not needed, just remove next parameters
publicDir: __dirname + '/../public',
publicIndex: 'index.html', // or false
staticCompress: true, // support compresion gzip, br, deflate
staticLastModified: true, // send last modified header for static files
// list of controllers
controllers: {
home: HomeController
}
},
// added mixin UwsServer to current services
mixins: [
UwsServer
],
created: this.createService
})
}
createService() {
// register routing where home is the controller and index is the method
this.createRoute('get / #c:home.index')
}
}
module.exports = AppService
<request type> / #c:<controller name>.<action>
<request type> / #s:<service name>.<action>
any
- HTTP ALLconnect
- HTTP CONNECTdel
- HTTP DELETEget
- HTTP GEThead
- HTTP HEADoptions
- HTTP OPTIONSpatch
- HTTP PATCHpost
- HTTP POSTput
- HTTP PUTtrace
- HTTP TRACE<request type> /articles/:id? #c:article.actionIndex
<request type> /articles/:id(\d+) #c:article.actionView
get id param value in controller
this.req.getParameter('id') // or this.req.getParameter('0')
// or
// this.inidReuqstData();
// this.requestData.parameters.id
cache
- second http cacheonBefore(route, req, res)
- Function before call for controller or serviceonAfter(route, req, res, data)
- Function after call for controller or serviceExample options for createRoute
this.createRoute('get / #c:home.index', {cache: 5});
property | description |
---|---|
requestData | read request data |
cookieData | read/write cookie |
redirectType | "header" | "meta" | "js" (default meta) |
format | default response content type default html |
statusCode | default response http code number 200 |
statusCodeText | default response http code string 200 OK |
broker | link ServiceBroker molecular.js |
req | link HttpRequest uWebsocket.js |
res | link HttpResponse uWebsocket.js |
requestData or cookieData
(The property objects are available after executing the this.initRequest()
method inside the controller method)
.timer
.start()
β Starts the timer..stop()
β Stops the timer. and Returns elapsed time in milliseconds..initJWT(key, iat = false)
.getJWT()
.createJwtToken(payload = {})
.extractJwtToken(token)
.initRequest()
.readBody()
.asJson(obj, httpCode = 200)
.renderRaw({ view, httpCode, format })
.render({ template, params, httpCode, format })
.setStatus(httpCode)
.writeHeader(key, value)
.setCorsHeaders()
.redirect(location, httpCode = 301)
redirectType
property of the controller.response json object
class Home extends AbstractController {
async index() {
return this.asJson({}, 200);
}
}
response redirect to other url
class Home extends AbstractController {
async index() {
return this.redirect('https://youdomain.dev', 301 /* optional*/ , "meta" /* optional*/ );
}
}
response ejs template
class Home extends AbstractController {
async index() {
return this.render({
template, params, httpCode: 200, format: 'html'
});
}
}
response raw
class Home extends AbstractController {
async index() {
return this.renderRaw({view: 'string', httpCode: 200, format: 'html'});
}
}
or
class Home extends AbstractController {
async index() {
return 'Hello World'
}
}
const { AbstractController } = require('node-moleculer-web');
module.exports = class Home extends AbstractController {
/**
* Initialize request data and cookie handler
*/
async index() {
// Initialize requestData and cookieData
this.initRequest();
// π Read a cookie value, with fallback
const cookieValue = this.cookieData.get('my_cookievalue', String(Date.now() /* or 1*new Date() */ ));
// βοΈ Set/update the cookie with a new value
this.cookieData.set('my_cookievalue', cookieValue);
// π€ Return current cookie value as response
return `Current cookie value: ${cookieValue}`;
}
};
const { AbstractController } = require('node-moleculer-web');
module.exports = class Home extends AbstractController {
/**
* Handle GET request and return parsed request data
*/
async index() {
// Initialize request and cookie utilities
this.initRequest();
// Extract request data
const headers = this.requestData.headers; // All request headers
const ip = this.requestData.ip; // Client IP address
const query = this.requestData.query ?? {}; // Query parameters
const referer = this.requestData.referer; // Referrer URL
const currentUrl = this.requestData.url; // Current request URL
const userAgent = this.requestData.userAgent; // User-Agent string
// Return all data as JSON response
return this.asJson({
headers,
ip,
query,
referer,
currentUrl,
userAgent
}, 200);
}
};
const { AbstractController } = require('node-moleculer-web');
module.exports = class Home extends AbstractController {
/**
* Calls another microservice and returns the result as JSON
*/
async index() {
try {
const data = await this.broker.call('service-name.action', {
email: 'test@example.com'
}) ?? {};
return this.asJson(data, 200);
} catch (error) {
return this.asJson({
error: error.message,
code: error.code || 500
}, error.code || 500);
}
}
};
const { AbstractController } = require('node-moleculer-web');
module.exports = class Home extends AbstractController {
/**
* Reads the request body and returns it as JSON
*/
async index() {
try {
const body = await this.readBody();
return this.asJson({ body }, 200);
} catch (error) {
return this.asJson({
error: 'Failed to read request body',
message: error.message
}, 400);
}
}
};
class Home extends AbstractController {
// create token
async index() {
this.initJWT('mykey');
const payload = {userId: 0, status: true};
const token = this.getJWT().create(payload)
return this.asJson({token}, 200);
}
// extract payload for token + validation (is payload not null then token valid)
async test() {
this.initRequest()
const token = this.requestData.query.token ?? '';
this.initJWT('mykey', false);
const payload = this.getJWT().extract(token)
return this.asJson({payload}, 200);
}
}
const {HttpService} = require('node-moleculer-web');
const {Service} = require('moleculer');
class RestService extends Service {
constructor(broker) {
super(broker);
this.parseServiceSchema({
name: 'rest',
settings: {},
mixins: [
HttpService // add HttpService mixin
],
actions: {
hello: {
rest: 'GET /hello',
handler(ctx) {
return 'Hello1 API Gateway!'
}
},
hello2: {
rest: 'GET /hello2/:test1/:test2',
handler(ctx) {
// read request data for meta object
console.log('requestData', ctx.meta.requestData)
// read cookie
ctx.meta.cookieData.get('test', 0);
// write cookie
ctx.meta.cookieData.set('test', 2);
// write header
ctx.meta.headers['my-custom-header'] = 'lama';
return 'Hello2 API Gateway!'
}
},
testJson: {
rest: 'GET /hello3/test/json',
handler(ctx) {
return this.asJson(ctx, {
myvalue: 111
})
}
},
testRedirect: {
rest: 'GET /hello3/test/redirect',
handler(ctx) {
return this.redirect(ctx, 'https://google.com', 301, 'meta')
}
}
},
});
}
}
server {
listen 80;
listen 443 ssl;
listen [::]:80;
listen [::]:443;
server_name domain.com;
location / {
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://127.0.0.1:3001;
proxy_redirect off;
}
}
Run locally
npx moleculer-runner -i 4 services
or
node node_modules/.bin/moleculer-runner -i 4 services
node
or ( list
added version 1.2.1)upstream node_apps {
server 127.0.0.1:3001;
server 127.0.0.1:3002;
server 127.0.0.1:3003;
server 127.0.0.1:3004;
}
server {
listen 80;
listen 443 ssl;
listen [::]:80;
listen [::]:443;
server_name domain.com;
location / {
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://node_apps;
proxy_redirect off;
}
}
cluster config moleculer.config.js
module.exports = {
nodeID: 'DEMO',
transporter: "TCP",
registry: {
// type of call strategy for microservices
strategy: "RoundRobin",
// If set to true, then each webserver will use only its own micro-services
preferLocal: false,
},
logger: console
};
run app
node tests/services/local.js
run strestest minimal logic
bzt tests/bzt-config.yaml
22:41:17 INFO: Test duration: 0:06:03
22:41:17 INFO: Samples count: 12909515, 0.00% failures
22:41:17 INFO: Average times: total 0.008, latency 0.008, connect 0.000
22:41:17 INFO: Percentiles:
+---------------+---------------+
| Percentile, % | Resp. Time, s |
+---------------+---------------+
| 0.0 | 0.0 |
| 50.0 | 0.006 |
| 90.0 | 0.016 |
| 95.0 | 0.018 |
| 99.0 | 0.025 |
| 99.9 | 0.038 |
| 100.0 | 0.058 |
+---------------+---------------+
22:41:17 INFO: Request label stats:
+---------------------------------------------------------------------------+--------+---------+--------+-------+
| label | status | succ | avg_rt | error |
+---------------------------------------------------------------------------+--------+---------+--------+-------+
| http://localhost:8080/bzt?id=39641&&hash=104bdfd40acf8d03e6b485e11b681fd4 | OK | 100.00% | 0.016 | |
| http://localhost:8080/bzt?id=39641&&hash=104bdfd40acf8d03e6b485e11b681fd5 | OK | 100.00% | 0.006 | |
| http://localhost:8080/bzt?id=39641&&hash=104bdfd40acf8d03e6b485e11b681fd6 | OK | 100.00% | 0.005 | |
| http://localhost:8080/bzt?id=39641&&hash=104bdfd40acf8d03e6b485e11b681fd7 | OK | 100.00% | 0.005 | |
| http://localhost:8080/bzt?id=39641&&hash=104bdfd40acf8d03e6b485e11b681fd8 | OK | 100.00% | 0.006 | |
+---------------------------------------------------------------------------+--------+---------+--------+-------+
FAQs
Fast web app service for moleculer.js + uWebSockets.js
The npm package node-moleculer-web receives a total of 3 weekly downloads. As such, node-moleculer-web popularity was classified as not popular.
We found that node-moleculer-web demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago.Β It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
This episode explores the hard problem of reachability analysis, from static analysis limits to handling dynamic languages and massive dependency trees.
Security News
/Research
Malicious Nx npm versions stole secrets and wallet info using AI CLI tools; Socketβs AI scanner detected the supply chain attack and flagged the malware.
Security News
CISAβs 2025 draft SBOM guidance adds new fields like hashes, licenses, and tool metadata to make software inventories more actionable.