Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

moleculer-web

Package Overview
Dependencies
Maintainers
1
Versions
67
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

moleculer-web - npm Package Compare versions

Comparing version 0.4.0 to 0.4.1

40

CHANGELOG.md

@@ -0,1 +1,41 @@

<a name="0.4.1"></a>
# 0.4.1 (2017-07-24)
## New
### Prohibited action with `publish: false` action properties
```js
module.exports = {
name: "test",
actions: {
dangerZone: {
publish: false,
handler(ctx) {
return "You cannot call this action via API Gateway!";
}
}
}
};
```
### Calling options in routes
The `route` has a `callOptions` property which is passed to `broker.call`. So you can set `timeout`, `retryCount` or `fallbackResponse` options for routes.
```js
broker.createService(ApiGatewayService, {
settings: {
routes: [{
callOptions: {
timeout: 1000, // 1 sec
retryCount: 0
}
}]
}
});
```
-----------------------------
<a name="0.4.0"></a>

@@ -2,0 +42,0 @@ # 0.4.0 (2017-07-07)

@@ -189,2 +189,7 @@ "use strict";

callOptions: {
timeout: 3000,
//fallbackResponse: "Fallback response via callOptions"
},
onBeforeCall(ctx, route, req, res) {

@@ -191,0 +196,0 @@ return new this.Promise(resolve => {

"use strict";
const _ = require("lodash");
const { MoleculerError } = require("moleculer").Errors;

@@ -36,4 +37,20 @@ module.exports = {

return "Hi!";
},
dangerZone: {
publish: false,
handler(ctx) {
return "You cannot call this action via API Gateway!";
}
},
slow(ctx) {
let time = ctx.params.delay || 5000;
return this.Promise.resolve().delay(time).then(() => `Done after ${time / 1000} sec!`);
},
wrong(ctx) {
throw new MoleculerError("It is a wrong action! I always throw error!");
}
}
};

8

package.json
{
"name": "moleculer-web",
"version": "0.4.0",
"version": "0.4.1",
"description": "Official API Gateway service for Moleculer framework",

@@ -32,3 +32,3 @@ "main": "index.js",

"coveralls": "2.13.1",
"eslint": "4.1.1",
"eslint": "4.3.0",
"express": "4.15.3",

@@ -39,5 +39,5 @@ "fakerator": "0.3.0",

"jsonwebtoken": "7.4.1",
"lolex": "1.6.0",
"lolex": "2.1.1",
"mkdirp": "0.5.1",
"moleculer": "0.8.2",
"moleculer": "0.8.3",
"multer": "1.3.0",

@@ -44,0 +44,0 @@ "nats": "0.7.20",

@@ -127,2 +127,10 @@ /*

// Call options
route.callOptions = opts.callOptions;
// Fallback response handler
/*if (opts.fallbackResponse)
route.fallbackResponse = this.Promise.method(opts.fallbackResponse);
*/
// Handle whitelist

@@ -240,5 +248,6 @@ route.whitelist = opts.whitelist;

* @param {String} url
* @param {Number} status code
*/
sendRedirect(res, url) {
res.writeHead(302, {
sendRedirect(res, url, code = 302) {
res.writeHead(code, {
"Location": url

@@ -384,141 +393,168 @@ });

// Whitelist check
.then(() => {
if (route.hasWhitelist) {
if (!this.checkWhitelist(route, actionName)) {
this.logger.debug(` The '${actionName}' action is not in the whitelist!`);
return this.Promise.reject(new ServiceNotFoundError(actionName));
.then(() => {
if (route.hasWhitelist) {
if (!this.checkWhitelist(route, actionName)) {
this.logger.debug(` The '${actionName}' action is not in the whitelist!`);
return this.Promise.reject(new ServiceNotFoundError(actionName));
}
}
}
})
})
// Parse body
.then(() => {
if (["POST", "PUT", "PATCH"].indexOf(req.method) !== -1 && route.parsers && route.parsers.length > 0) {
return this.Promise.mapSeries(route.parsers, parser => {
return new this.Promise((resolve, reject) => {
parser(req, res, err => {
if (err) {
return reject(new InvalidRequestBodyError(err.body, err.message));
}
// Parse body
.then(() => {
if (["POST", "PUT", "PATCH"].indexOf(req.method) !== -1 && route.parsers && route.parsers.length > 0) {
return this.Promise.mapSeries(route.parsers, parser => {
return new this.Promise((resolve, reject) => {
parser(req, res, err => {
if (err) {
return reject(new InvalidRequestBodyError(err.body, err.message));
}
resolve();
resolve();
});
});
});
});
}
})
}
})
// Merge params
.then(() => {
const body = _.isObject(req.body) ? req.body : {};
params = Object.assign({}, body, params);
})
// Merge params
.then(() => {
const body = _.isObject(req.body) ? req.body : {};
params = Object.assign({}, body, params);
})
// Resolve action by name
.then(() => {
endpoint = this.broker.getAction(actionName);
if (endpoint) {
// Resolve action by name
.then(() => {
endpoint = this.broker.getAction(actionName);
if (!endpoint) {
// Action is not available
return this.Promise.reject(new ServiceNotFoundError(actionName));
}
if (endpoint.action.publish === false) {
// Action is not publishable
return this.Promise.reject(new ServiceNotFoundError(actionName));
}
// Validate params
if (this.broker.validator && endpoint.action.params)
this.broker.validator.validate(params, endpoint.action.params);
} else {
// Action is not available
return this.Promise.reject(new ServiceNotFoundError(actionName));
}
this.broker.validator.validate(params, endpoint.action.params);
return endpoint;
})
return endpoint;
})
// Create a new context for request
.then(() => {
this.logger.info(` Call '${actionName}' action with params:`, params);
// Create a new context for request
.then(() => {
this.logger.info(` Call '${actionName}' action with params:`, params);
const restAction = {
name: this.name + ".rest"
};
const restAction = {
name: this.name + ".rest"
};
// Create a new context to wrap the request
const ctx = this.broker.createNewContext(restAction, null, params, {
//timeout: 5 * 1000
});
ctx.requestID = ctx.id;
ctx._metricStart(ctx.metrics);
//ctx.endpoint = endpoint;
// Create a new context to wrap the request
const ctx = this.broker.createNewContext(restAction, null, params, route.callOptions || {});
return ctx;
})
ctx.requestID = ctx.id;
ctx._metricStart(ctx.metrics);
//ctx.endpoint = endpoint;
// onBeforeCall handling
.then(ctx => {
if (route.onBeforeCall) {
return route.onBeforeCall.call(this, ctx, route, req, res).then(() => {
return ctx;
});
}
return ctx;
})
return ctx;
})
// Authorization
.then(ctx => {
if (route.authorization) {
return this.authorize(ctx, route, req, res).then(() => {
return ctx;
});
}
return ctx;
})
// onBeforeCall handling
.then(ctx => {
if (route.onBeforeCall) {
return route.onBeforeCall.call(this, ctx, route, req, res).then(() => {
return ctx;
});
}
return ctx;
})
// Call the action
.then(ctx => {
return ctx.call(endpoint, params)
.then(data => {
res.statusCode = 200;
// Authorization
.then(ctx => {
if (route.authorization) {
return this.authorize(ctx, route, req, res).then(() => {
return ctx;
});
}
return ctx;
})
// Override responseType by action
const responseType = endpoint.action.responseType;
// Call the action
.then(ctx => {
return ctx.call(endpoint, params, route.callOptions || {})
.then(data => {
res.statusCode = 200;
// Return with the response
if (ctx.requestID)
res.setHeader("Request-Id", ctx.requestID);
// Override responseType by action
const responseType = endpoint.action.responseType;
return Promise.resolve()
// Return with the response
if (ctx.requestID)
res.setHeader("Request-Id", ctx.requestID);
return Promise.resolve()
// onAfterCall handling
.then(() => {
if (route.onAfterCall)
return route.onAfterCall.call(this, ctx, route, req, res, data);
})
.then(() => {
.then(() => {
if (route.onAfterCall)
return route.onAfterCall.call(this, ctx, route, req, res, data);
})
.then(() => {
//try {
this.sendResponse(ctx, route, req, res, data, responseType);
//} catch(err) {
this.sendResponse(ctx, route, req, res, data, responseType);
//} catch(err) {
/* istanbul ignore next */
// return this.Promise.reject(new InvalidResponseTypeError(typeof(data)));
//}
// return this.Promise.reject(new InvalidResponseTypeError(typeof(data)));
//}
ctx._metricFinish(null, ctx.metrics);
});
});
})
ctx._metricFinish(null, ctx.metrics);
});
});
})
// Error handling
.catch(err => {
this.logger.error(" Request error!", err.name, ":", err.message, "\n", err.stack, "\nData:", err.data);
const headers = {
"Content-type": "application/json"
};
if (err.ctx) {
headers["Request-Id"] = err.ctx.id;
}
// Error handling
.catch(err => {
return Promise.resolve(err)
/* Deprecated. Use `route.callOptions.fallbackResponse` instead.
.then(err => {
let ctx = err.ctx;
if (_.isFunction(route.fallbackResponse)) {
return route.fallbackResponse.call(this, err, route, err.ctx, req, res)
.then(data => {
if (data !== undefined) {
this.sendResponse(ctx, route, req, res, data);
return null;
}
return null;
}).catch(err => err); // Throw further the new Error
}
return err;
})
*/
.then(err => {
/* istanbul ignore next */
if (!err)
return;
// Return with the error
const code = _.isNumber(err.code) ? err.code : 500;
res.writeHead(code, headers);
const errObj = _.pick(err, ["name", "message", "code", "type", "data"]);
res.end(JSON.stringify(errObj, null, 2));
this.logger.error(" Request error!", err.name, ":", err.message, "\n", err.stack, "\nData:", err.data);
const headers = {
"Content-type": "application/json"
};
if (err.ctx) {
headers["Request-Id"] = err.ctx.id;
}
if (err.ctx)
err.ctx._metricFinish(null, err.ctx.metrics);
});
// Return with the error
const code = _.isNumber(err.code) ? err.code : 500;
res.writeHead(code, headers);
const errObj = _.pick(err, ["name", "message", "code", "type", "data"]);
res.end(JSON.stringify(errObj, null, 2));
if (err.ctx)
err.ctx._metricFinish(null, err.ctx.metrics);
});
});
return p;

@@ -525,0 +561,0 @@ },

@@ -37,2 +37,9 @@ "use strict";

dangerZone: {
publish: false,
handler(ctx) {
return "Danger zone!";
}
},
text(ctx) {

@@ -39,0 +46,0 @@ return "String text";

@@ -114,2 +114,20 @@ "use strict";

});
it("GET /test/dangerZone", () => {
return request(server)
.get("/test/dangerZone")
.expect(404)
.expect("Content-Type", "application/json")
.then(res => {
expect(res.body).toEqual({
"code": 404,
"message": "Service 'test.dangerZone' is not available!",
"name": "ServiceNotFoundError",
"type": null,
"data": {
action: "test.dangerZone"
}
});
});
});
});

@@ -544,2 +562,6 @@

let customAlias = jest.fn((route, req, res) => {
res.end("Custom Alias");
});
beforeAll(() => {

@@ -556,3 +578,4 @@ [ broker, service, server] = setup({

"/repeat-test/:args*": "test.echo",
"GET /": "test.hello"
"GET /": "test.hello",
"GET custom": customAlias
}

@@ -700,2 +723,13 @@ }]

});
it("GET /api/custom", () => {
return request(server)
.get("/api/custom")
.expect(200)
.then(res => {
expect(res.text).toBe("Custom Alias");
expect(customAlias).toHaveBeenCalledTimes(1);
expect(customAlias).toHaveBeenCalledWith(service.routes[0], jasmine.any(http.IncomingMessage), jasmine.any(http.ServerResponse));
});
});
});

@@ -702,0 +736,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc