moleculerjs / moleculer-web Goto Github PK
View Code? Open in Web Editor NEW:earth_africa: Official API Gateway service for Moleculer framework
Home Page: http://moleculer.services/docs/moleculer-web.html
License: MIT License
:earth_africa: Official API Gateway service for Moleculer framework
Home Page: http://moleculer.services/docs/moleculer-web.html
License: MIT License
Allow for each service to have its own Rate Limit setting (similar to the rate limiter in API Gateway).
Hi!
chalk
is missing in package.json
, because of this, the use of moleculer-web
as a dependency with npm install --production
is impossible.
Trying to do something like:
cors: {
origin: ['http://localhost:3000', 'http://localhost:4000'],
methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'DELETE'],
credentials: true,
},
I'm getting the following error:
login:1 Failed to load [my_page]: Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header contains multiple values 'http://localhost:3000, http://localhost:4000', but only one is allowed. Origin 'http://localhost:4000' is therefore not allowed access.
Reading through I think the solution would be something like:
} else if (Array.isArray(route.cors.origin)) {
const origin = req.headers['origin'];
if(route.cors.origin.indexOf(origin) > -1) {
res.setHeader("Access-Control-Allow-Origin", origin);
res.setHeader("Vary", "Origin");
}
}
rather than the current one:
Lines 922 to 925 in 08cdc3c
Following, a reference on how HapiJs is doing it:
https://github.com/hapijs/hapi/blob/574d768b2648a6b2e404225d2771cb0220ed9d97/lib/cors.js#L48-L55
I am creating a PR and adding the wildcard to origins such as "localhost:*". Let me know if it's ok for you.
Sources:
https://blog.crashtest-security.com/multiple-values-access-control-allow-origin-3c7cafc8c5c0
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Access-Control-Allow-Origin
This is my code in an action:
ctx.meta.$responseStatus = 401;
ctx.meta.$responseType = "text/plain";
return {"message": "Unauthorized"};
But it always response 200 code.
The only way that I made this working, is throwing an error in the action and catching it with onError in the settings like this:
onError(req, res, err) {
res.setHeader("Content-Type", "text/plain");
res.writeHead(401);
return res.end("Unauthorized");
}
But it prints the whole stack error, and I don't want this.
Do you know if I'm doing anything wrong?
I just found that we can type api/v1/../../content
and we get parents (skips v1 and so on)
Where to look to fix this ?
Code to reproduce:
const { ServiceBroker } = require('moleculer')
const ApiService = require('moleculer-web')
const broker = new ServiceBroker()
broker.createService({
name: 'api-gateway',
mixins: [
ApiService
],
settings: {
routes: [{
path: '/',
mappingPolicy: 'restrict',
aliases: {
'GET /': '$node.health'
}
}, {
path: '/healthz',
mappingPolicy: 'restrict',
aliases: {
'GET /': '$node.health'
}
}]
}
})
broker.start()
Expected Result:
Both GET / and GET /healthz should the node health response
Actual Result:
GET / will work and respond with the node health
GET /healthz returns an HTTP 404 Error
How to add a new service/action to a moleculer-web service without restarting .
Example i have created a index.js ad loaded math.service .js which contains only add functionality and started the service .Its working fine now i added code for sub in math.service.js file and reloading it but i am unable to access this action without restarting index .js
Please let me know how can i add a new service/ action without restarting
Validator adds a validation middleware which does the params validation. by doing this in moleculer-web
it skips all other middleware
validator.validate
throws ValidationError
Browser sends a OPTIONS
request to determine cors and when using something like:
aliases: {
'POST login': 'v1.auth.login',
}
it won't work since OPTIONS
request is not allowed. This will work, however:
aliases: {
'OPTIONS login': 'v1.auth.login',
'POST login': 'v1.auth.login',
}
Multer to embed in the main code and display the parameters as done by bodyParser?
...
routes: [
{
path: "/api",
multer: {
dest: "./uploads/",
fields: [{ name: "logo", maxCount: 1}, { name: 'gallery', maxCount: 8 }],
},
aliases: {
"REST sites": "sites",
},
},
...
]
In service ctx.files.logo
and ctx.files.gallery
Hi,
I'm trying to create a service with express following the example. But it doesn't work. It's always raising this error:
ServiceSchemaError: Service name can't be empty! Maybe it is not a valid Service schema.
I only removed the external dependcy with the test service in order to simplify it.
This is the code. Thanks in advance.
"use strict";
let { ServiceBroker } = require("moleculer");
let ApiGatewayService = require("moleculer-web");
let express = require("express");
// Create broker
let broker = new ServiceBroker({
logger: console
});
// Load API Gateway
const svc = broker.createService({
mixins: ApiGatewayService,
name: "myservice",
settings: {
middleware: true
}
});
// Create Express application
const app = express();
// Use ApiGateway as middleware
app.use("/api", svc.express());
// Listening
app.listen(3333, err => {
if (err)
return console.error(err);
console.log("Open http://localhost:3333/api/test/hello");
});
// Start server
broker.start();
Since Moleculer v.012 ctx.meta
comes back to the caller. It means requests send context meta information back to API Gateway, like response status code, response headers, response content type...etc.
Meta keys what API Gateway will process:
ctx.meta.$responseType
- set Content-Type
in responsectx.meta.$responseHeaders
- set custom response headersctx.meta.$responseStatus
- set HTTP status code in responsectx.meta.$location
- redirect location when the $responseStatus
is 3xxExample
{
exportData(ctx) {
// Set meta for API GW
ctx.meta.$responseStatus = 200;
ctx.meta.$responseType = "text/csv; charset=utf-8";
ctx.meta.$responseHeaders = {
"Content-Disposition": 'attachment; filename=\"data.csv\"'
}
// Return data
return this.getAllRows();
}
}
And in middlevare I tried:
use: [ cookieParser(), function(req, res, next){ req.socket.server.setTimeout(600000); next(); } ]
The code in the hook created()
this.server.setTimeout(600000);
The result was not given
Tell me, please, the more correct method!?
Hello,
I would like add a request for enhancement HTTP 2 support protocol
Congratulations for this framework!
Need support to redirect all http requests to https for assets.
Using a middleware for force redirect only act on the services and not the asset load.
I wrote an afterHook to set the content type to include the utf-8 charset option (I have international characters in my json responses) like this:
onAfterCall(ctx, route, req, res) {
res.setHeader('Content-Type', 'application/json; charset=utf-8');
}
Unfortunately, this gets overwritten by the built-in behavior.
I think it should check whether or not the header is already set before setting it.
When using error handling middleware as described in the documentation a RequestTimeoutError is raised.
Clone this repo and cd
into it. The repo contains a standard moleculer project with an api service. The api service includes two middlewares:
Run docker-compose up
and then curl http://localhost:3000/api/greeter/hello
The JSON response returned is:
{
"name": "Error",
"message": "Something went wrong",
"code": 500
}
The console log of the api service is:
api_1 | [2018-07-15T10:03:16.897Z] INFO 0e908e290bf5-16/API: => GET /api/greeter/hello
api_1 | [2018-07-15T10:03:16.900Z] ERROR 0e908e290bf5-16/API: Error is occured in middlewares!
api_1 | [2018-07-15T10:03:16.908Z] INFO 0e908e290bf5-16/API: <= 500 GET /api/greeter/hello [+11.965 ms]
api_1 | [2018-07-15T10:03:16.908Z] INFO 0e908e290bf5-16/API:
The JSON response returned is:
{
"name": "Error",
"message": "Something went wrong",
"code": 500
}
The console log of the api service is (after 10 seconds):
api_1 | [2018-07-15T10:03:16.897Z] INFO 0e908e290bf5-16/API: => GET /api/greeter/hello
api_1 | [2018-07-15T10:03:16.900Z] ERROR 0e908e290bf5-16/API: Error is occured in middlewares!
api_1 | [2018-07-15T10:03:16.908Z] INFO 0e908e290bf5-16/API: <= 500 GET /api/greeter/hello [+11.965 ms]
api_1 | [2018-07-15T10:03:16.908Z] INFO 0e908e290bf5-16/API:
api_1 | [2018-07-15T10:03:26.927Z] WARN 0e908e290bf5-16/BROKER: Request 'api.rest' is timed out. { requestID: null, nodeID: '0e908e290bf5-16', timeout: 10000 }
api_1 | [2018-07-15T10:03:26.932Z] ERROR 0e908e290bf5-16/API: Request error! RequestTimeoutError : Request is timed out when call 'api.rest' action on '0e908e290bf5-16' node.
api_1 | RequestTimeoutError: Request is timed out when call 'api.rest' action on '0e908e290bf5-16' node.
api_1 | at p.timeout.catch.err (/app/node_modules/moleculer/src/middlewares/timeout.js:33:13)
api_1 | at tryCatcher (/app/node_modules/bluebird/js/release/util.js:16:23)
api_1 | at Promise._settlePromiseFromHandler (/app/node_modules/bluebird/js/release/promise.js:512:31)
api_1 | at Promise._settlePromise (/app/node_modules/bluebird/js/release/promise.js:569:18)
api_1 | at Promise._settlePromise0 (/app/node_modules/bluebird/js/release/promise.js:614:10)
api_1 | at Promise._settlePromises (/app/node_modules/bluebird/js/release/promise.js:689:18)
api_1 | at Async._drainQueue (/app/node_modules/bluebird/js/release/async.js:133:16)
api_1 | at Async._drainQueues (/app/node_modules/bluebird/js/release/async.js:143:10)
api_1 | at Immediate.Async.drainQueues (/app/node_modules/bluebird/js/release/async.js:17:14)
api_1 | at runCallback (timers.js:810:20)
api_1 | at tryOnImmediate (timers.js:768:5)
api_1 | at processImmediate [as _immediateCallback] (timers.js:745:5)
api_1 | Data: { action: 'api.rest', nodeID: '0e908e290bf5-16' }
api_1 | [2018-07-15T10:03:26.933Z] WARN 0e908e290bf5-16/API: Headers have already sent
The api service makes use of two middlewares as documented:
'use strict';
const ApiGateway = require('moleculer-web');
module.exports = {
name: 'api',
mixins: [ApiGateway],
// More info about settings:
// https://moleculer.services/docs/0.13/moleculer-web.html
settings: {
// ...
use: [
// simulate a middleware error
(req, res, next) => {
next(new Error('Something went wrong'))
},
// simulate a error handling middleware
function (err, req, res, next) {
this.logger.error('Error is occured in middlewares!');
this.sendError(req, res, err);
},
],
},
};
The first middleware simulates a middleware error (by simply calling next
with an Error). The second middleware handles the error by sending an error response. A real world use case for this is when for example using swagger-tools middleware to perform request validation. This middleware calls next(RequestValidationError)
. These errors should be handeled error in the request-response flow (no necessity to call an action). When reading the sources of moleculer-web
I could pin the cause for this issue to these segments:
// moleculer-web/src/index.js:216
routeHandler(ctx, route, req, res) {
// ...
return this.composeThen(req, res, ...route.middlewares).then(() => {
// ...
return this.aliasHandler(req, res, { action });
})
},
Here the http request is handled by a route. First all middlewares are invoked in a serial promise chain. Upon resolve the action is resolved and invoked. The issue here is that by definition connect-like middleware can terminate the request early (by sending a response). This means that composeThen
in this case is never being resolved. This causes the context to raise a TimeOutError.
The potentially easiest solution could be to remove the documentation for error handling middleware, or explicitly state that this is not working and instead the service should be invoked in middleware mode. In this case for example express
can invoke the middlewares prior to a moluculer service context existing. Downside is that with such an implementation to my understanding some moleculer features like service dependencies or hot reloading could not work.
An alternative could be to do something like:
return Promise.race([
this.composeThen(),
new Promise((resolve,reject) => {
setTimeout(3000,() => {
response.finished ? reject(MiddleWareEarlyTerminationError) : reject(MiddleWareTimeoutError)
})
})
]).then(/* ... */)
In this case the middleware would race against a timeout. If after the timeout there was no response send to the client, the promise would be rejected with a MiddleWareTimeoutError
. If a response has been send, the promise rejects with a MiddleWareEarlyTerminationError
. The http handler could then, when catching on the promise compair the error and if it is a MiddleWareEarlyTerminationError
be silent about it. The problem here is that I do not know if at this stage the timeout to race for can be savely determined. I think this would also be early enough to not interfere with rate limiting and such.
It's a bit hacky of course.
I think the underlying problem is that the moleculer context (broker invoking action) is created to early here. Calling an action does (and should) allways expect an answer and handle timeouts. However the way middlewares work, this behavior does not necessarily occur here. I think the correct way would be to have a container running (at least for the global middlewares), which could be based on connect
or sth, and only when the global middlewares passed, the api.rest
action should actually be invoked. However I am far to inexperienced with moleculer to judge the feasibility or even correctness of this approach.
I am making a REST call from one web service to a node js microservice but request headers of the REST such as x-b3-traceid, x-b3-spanid etc. does not get passed thru molecular-web for tracing.
as Doc , i config it like this:
assets: {
// Root folder of assets
folder: "./public",
// Options to `server-static` module
options: {}
},
Then i write a index.html in ./public/index.html
, But i try those URL, all can't get the index.html
/index.html
/api/index.html
/api/public/index.html
/api/public/api/public/index.html
/api/api/public/index.html
I recently ran into a "bug" where I would call a service: example.com/api/hello
and I would get a 404 since the service is not up yet, but the gateway has the routes registered for this particular service.
Send a 503 if the service exists in the route whitelist/aliases
import { Errors } from 'moleculer'
import _ = require('lodash');
onError(req, res, err) {
switch (err.constructor) {
case Errors.ServiceNotFoundError:
err.message = 'Service not found';
if (_.findIndex(this.routes[0].whitelist, i => i == err.data.action) != -1) {
err.message = 'Service unavailable';
err.code = 503;
}
break;
}
}
routes: [{
path: "/admin",
whitelist: [
"debug.log"
],
}, {
path: "/api",
whitelist: [
"debug.log"
],
}],
In such case, the ctx.params is empty on POST request, on the 2nd route.
E.g:
On the /admin/debug/log everything is fine.
On the /api/debug/log the ctx.params is empty.
Any suggestions?
Hi Team
I was following your instructions on how to create a Moleculer project but I run npm install moleculer-cli -g and moleculer init project moleculer-demo i get the below error:
Template repo: moleculerjs/moleculer-template-project
Failed to download repo from 'moleculerjs/moleculer-template-project'!
Since route middlewares signature is this : function(req, res, next) {...}
, I wondered how to access the ctx object and add meta data to it
{
settings: {
logRequestParams: "debug", // log with "debug" level
logResponseData: null, // doesn't log
}
Hello,
I'm trying to use CORS in my project, but I think that the server is responding an OPTIONS event with a POST response.
Code:
settings: {
port: process.env.PORT || 3000,
ip: '0.0.0.0',
bodyParsers: {
json: true
},
cors: {
origin: '*',
methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'DELETE'],
allowedHeaders: [],
exposedHeaders: [],
credentials: false,
maxAge: 3600
},
routes: [
{
path: '/api',
aliases: {
'POST /user/login': 'user.login'
},
cors: {
origin: ['http://localhost:4200'],
methods: ['GET', 'OPTIONS', 'POST'],
credentials: true
},
mappingPolicy: 'restrict',
authorization: true
}
]
},
Have any idea?
This custom code works but only for "GET" method:
This is part of route config
// Set CORS headers
onBeforeCall(ctx, route, req, res) {
ctx.meta.headers = req.headers;
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Request-Method', '*');
res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
if ( req.method === 'OPTIONS' ) {
res.writeHead(200);
res.end();
return;
}
}
on POST method this does not work! (because of different logic in source code)
Would be nice to integrate CORS settings in some nice way
so we can easy add CORS settings for routes and also for aliased routes if possible
Currently you cannot map the url / to any service action.
I've created the PR #28 to address this.
moleculer-web: 0.3.3
Issuing a GET to a non existing route, for example http://localhost:3000/does-not-exist returns
{
"name": "ServiceNotFoundError",
"message": "Service 'does-not-exist' is not available!",
"code": 501,
"type": null,
"data": {
"action": "does-not-exist"
}
}
and sets the HTTP header
Status Code:501 Not Implemented
This status code is used when using a request method (standard ones are GET, POST, HEAD, PUT, ...) that the web server does not support.
I'm using the GET request method, which the web server supports, so I would not expect to get a 501 in this case.
For non existing resources, 404 Not Found should be used. It is a client error and should therefore be in the 4xx range (5xx are used for server errors).
I know the 501 originates from an error in moleculer and just passes through, but it's confusing to get it as the HTTP status code.
501: https://tools.ietf.org/html/rfc7231#section-6.6.2
404: https://tools.ietf.org/html/rfc7231#section-6.5.4
Request methods: https://tools.ietf.org/html/rfc7231#section-4
When using MoleculerError to create errors in my services which are in turn sent back to the api-gateway it exclusively sends http status code 200 back to the client regardless. I've tried adding a global onError handler aswell, but to no avail. When I return errors from moleculer-web (authorize function) it sends them back to the client correctly so I am assuming this is an issue with how data is being exchanged between the api gateway and the services and how errors are picked up.
What is the best practice here?
I have an alias on moleculer-web
but, the default URI is also accessible, then I can't expose the service action only in HTTP POST method. For example:
I have an actions: test.greeter
and I want to expose it only in HTTP POST method. Then I configure my alias:
{
path: '/api/main'
aliases:{
'POST greeters': 'test.greeter.create'
}
}
Now I have two URIs:
/api/main/greeters
/api/main/test/greeter/create
Alias make a 'back door' open for all HTTP methods and for unauthenticated consumers. Is there any solution? can I block the default URIs?
Add GraphQL support to the API Gateway, with ability to consolidate responses from multiple services, bases on the GraphQL schema definition.
I'm having a trouble with moleculer-web now, I'm always getting 500 as error code.
Scenario :
In my middleware I have the bellow code
try {
container = await req.$service.broker.call('store.canAcess', {
name: container,
access: access
});
} catch (e) {
console.log('e.code', e.code)//===>401
return next(e);
}
In my thought the error comes from here in moleculer-web
Line 505 in 1ba3656
err.status
as code witch is not defined on MoleculerClientError instances, so the new error created will have code equals to 500
Correct me if I'm missing something.
Handle params in aliases "GET posts/:id": "posts.get"
and set ctx.params.id
Hi,
Im trying to serve a vue app as a service following the conduit example.
I created a www.service.js inside services dir
www.service.js
"use strict";
let path = require("path");
const ApiGateway = require("moleculer-web");
const webpack = require("webpack");
const devMiddleware = require("webpack-dev-middleware");
const hotMiddleware = require("webpack-hot-middleware");
const serveStatic = require("serve-static");
const compression = require("compression");
const config = require("../webpack.config");
const compiler = webpack(config);
module.exports = {
name: "www",
middleware:false,
mixins: [ApiGateway],
settings: {
port: 3000,
routes: [
{
path: "/api",
aliases: {
"GET health": "$node.health",
},
bodyParsers: {
json: true,
urlencoded: { extended: true }
}
},
{
path: "/",
use: [
compression(),
devMiddleware(compiler, {
noInfo: true,
publicPath: config.output.publicPath,
headers: { "Access-Control-Allow-Origin": "*" }
}),
hotMiddleware(compiler),
serveStatic(path.join(__dirname, "../public"))
],
},
]
}
};
App is being served correctly but I get response timeouts.
2018-08-16T13:25:30.190Z] INFO desh-18794/WWW: => GET /app.js
[2018-08-16T13:25:30.326Z] INFO desh-18794/WWW: => GET /__webpack_hmr
[2018-08-16T13:25:40.332Z] WARN desh-18794/BROKER: Request 'www.rest' is timed out. { requestID: null, nodeID: 'desh-18794', timeout: 10000 }
[2018-08-16T13:25:40.334Z] ERROR desh-18794/WWW: Request error! RequestTimeoutError : Request is timed out when call 'www.rest' action on 'desh-18794' node.
RequestTimeoutError: Request is timed out when call 'www.rest' action on 'desh-18794' node.
at p.timeout.catch.err (/home/sarodspirit/Development/mf-back/node_modules/moleculer/src/middlewares/timeout.js:33:13)
at tryCatcher (/home/sarodspirit/Development/mf-back/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/home/sarodspirit/Development/mf-back/node_modules/bluebird/js/release/promise.js:512:31)
at Promise._settlePromise (/home/sarodspirit/Development/mf-back/node_modules/bluebird/js/release/promise.js:569:18)
at Promise._settlePromise0 (/home/sarodspirit/Development/mf-back/node_modules/bluebird/js/release/promise.js:614:10)
at Promise._settlePromises (/home/sarodspirit/Development/mf-back/node_modules/bluebird/js/release/promise.js:689:18)
at Async._drainQueue (/home/sarodspirit/Development/mf-back/node_modules/bluebird/js/release/async.js:133:16)
at Async._drainQueues (/home/sarodspirit/Development/mf-back/node_modules/bluebird/js/release/async.js:143:10)
at Immediate.Async.drainQueues (/home/sarodspirit/Development/mf-back/node_modules/bluebird/js/release/async.js:17:14)
at runCallback (timers.js:781:20)
at tryOnImmediate (timers.js:743:5)
at processImmediate [as _immediateCallback] (timers.js:714:5)
Data: { action: 'www.rest', nodeID: 'desh-18794' }
[2018-08-16T13:25:40.334Z] WARN desh-18794/WWW: Headers have already sent
Any clues about this ?
Hello,
Tested Code:
let { ServiceBroker } = require("moleculer");
let ApiService = require("moleculer-web");
let broker = new ServiceBroker({ logger: console });
broker.createService({
name: "math",
actions: {
// Shorthand definition, only the handler function
add(ctx) {
return Number(ctx.params.a) + Number(ctx.params.b);
},
// Normal definition with other properties. In this case
// the `handler` function is required!
mult: {
cache: false,
params: {
a: "number",
b: "number"
},
handler(ctx) {
// The action properties are accessible as `ctx.action.*`
if (!ctx.action.cache)
return Number(ctx.params.a) * Number(ctx.params.b);
}
}
}
});
// Load API Gateway
broker.createService(ApiService);
// Start server
broker.start().then(() => broker.repl());
GET => http://localhost:3000/math/add?a=25&b=13
RESULT: 38
GET => http://localhost:3000/math/mult?a=25&b=13
RESULT: {
"name": "ValidationError",
"message": "Parameters validation error!",
"code": 422,
"type": null,
"data": [
{
"type": "number",
"field": "a",
"message": "The 'a' field must be a number!"
},
{
"type": "number",
"field": "b",
"message": "The 'b' field must be a number!"
}
]
}
Probably some issue converting string to number.
Def:
aliases: {
"REST posts": "posts"
}
exposed to:
aliases: {
"GET posts": "posts.find",
"GET posts/:id": "posts.get",
"POST posts": "posts.create",
"PUT posts/:id": "posts.update",
"DELETE posts/:id": "posts.remove"
}
Hi,
I encounter 'unhandled rejection' error when upgrade moleculer-web v0.6.3 to v.0.8.0
and I've found error handler is missing on aliasHandler,
In my situation,
in authorize function, return promise with rejection I've got unhandled rejection error
return Promise.reject(new UnAuthorizedError(ERR_NO_TOKEN))
and my suggestion
src/index.js :392
// If not, it handled request/response by itself. Break the flow.
return true;
})
.catch(err => this.sendError(req, res, err));
},
I am making a REST call from an external web service (which is using spring-sleuth for distributed tracing at zipkin) to a node js microservice (which is using molecular-web framework), service is being called and result is returned however moleculer-web is not consuming x-b3-traceid & x-b3-spanid request headers used for distributed tracing and the tracing is working only when services are invoked using the broker directly.
Since the headers are not consumed by the called service, there is no tracing linking between these two services. Ideally, the called service should have caller service's id as parent id but in this case that is not happening, they are generating separate tracing graphs.
Additionally, the parent context is being created only when the it is called thru molecular node js service.
node-js-service.js:
.
.
.
actions: {
create(ctx) {
ctx.call("any-service", {
.
.
.
context.js:
.
.
.
call(actionName, params, opts = {}) {
opts.parentCtx = this;
.
.
.
I'm using Rest example and trying to add new service - post.service.js
Posts service starts - as seen in the log file
[2018-07-06T15:42:32.126Z] DEBUG node-1/BROKER: Broadcast '$services.changed' local event.
[2018-07-06T15:42:32.128Z] DEBUG node-1/BROKER: Load service 'posts.service.js'...
[2018-07-06T15:42:32.134Z] INFO node-1/REGISTRY: 'posts' service is registered.
[2018-07-06T15:42:32.134Z] DEBUG node-1/POSTS:v1: Created post service
[2018-07-06T15:42:32.135Z] DEBUG node-1/BROKER: Broadcast '$services.changed' local event.
[2018-07-06T15:42:32.136Z] DEBUG node-1/BROKER: Watching 'posts' service file...
[2018-07-06T15:42:32.138Z] DEBUG node-1/POSTS:v1: Post service strted
and is seen running
mol $ services
╔═════════╤═════════╤══════════╤═════════╤════════╤═══════╗
║ Service │ Version │ State │ Actions │ Events │ Nodes ║
╟─────────┼─────────┼──────────┼─────────┼────────┼───────╢
║ $node │ - │ OK │ 5 │ 0 │ 1 ║
║ api │ - │ OK │ 1 │ 0 │ 1 ║
║ greeter │ - │ OK │ 2 │ 0 │ 1 ║
║ posts │ 1 │ OK │ 2 │ 0 │ 1 ║
╚═════════╧═════════╧══════════╧═════════╧════════╧═══════╝
route alias is configured in api.service.js
routes: [ { path: '/posts', aliases: { "GET posts": "posts.get", "health": "$node.health" }, ...
but when I try to
[2018-07-06T15:41:18.874Z] INFO node-1/API: => GET /api/posts
[2018-07-06T15:41:18.912Z] WARN node-1/BROKER: Service 'posts' is not registered.
[2018-07-06T15:41:18.928Z] ERROR node-1/API: Request error! ServiceNotFoundError : Service 'posts' is not found.
ServiceNotFoundError: Service 'posts' is not found.
at ServiceBroker.findNextActionEndpoint (D:\dev\moleculertest1\apiservertest\node_modules\moleculer\src\service-broker.js:830:13)
at p.Promise.resolve.then (D:\dev\moleculertest1\apiservertest\node_modules\moleculer-web\src\index.js:634:29)
at tryCatcher (D:\dev\moleculertest1\apiservertest\node_modules\bluebird\js\release\util.js:16:23)
at Promise._settlePromiseFromHandler (D:\dev\moleculertest1\apiservertest\node_modules\bluebird\js\release\promise.js:512:31)
at Promise._settlePromise (D:\dev\moleculertest1\apiservertest\node_modules\bluebird\js\release\promise.js:569:18)
at Promise._settlePromiseCtx (D:\dev\moleculertest1\apiservertest\node_modules\bluebird\js\release\promise.js:606:10)
at Async._drainQueue (D:\dev\moleculertest1\apiservertest\node_modules\bluebird\js\release\async.js:138:12)
at Async._drainQueues (D:\dev\moleculertest1\apiservertest\node_modules\bluebird\js\release\async.js:143:10)
at Immediate.Async.drainQueues [as _onImmediate] (D:\dev\moleculertest1\apiservertest\node_modules\bluebird\js\release\async.js:17:14)
at runCallback (timers.js:696:18)
at tryOnImmediate (timers.js:667:5)
at processImmediate (timers.js:649:5)
Data: { action: 'posts', nodeID: undefined }
[2018-07-06T15:41:18.951Z] INFO node-1/API: <= 404 GET /api/posts
Hi there,
When alias handler is available, it returns on line 503 (pls. see link below). This skips preActionCall call. Which in turn skips authorize call, amongst other helpful function like onBeforeCall.
Line 503 in 08cdc3c
I need to return 'Content-Type' as xml and I used the following
ctx.meta.$responseType = "text/csv" as per documentation given in http://moleculer.services/docs/0.13/moleculer-web.html#Response-type-amp-status-code
Sadly it does not work and response goes with Content-Type of application/json ... Could you please get this corrected asap...
How do I change the maximum size of a request?
Attempt:
let bodyParser = require("body-parser");
and in settings:
{
...
bodyParser({ json: true, limit: 1024*1024*1 })
...
}
Has not given result: Global error: request entity too large.
Middleware error! { MoleculerError: request entity too large
at Service.compose.err (\node_modules\moleculer-web\src\index.js:452:24)
at next (\node_modules\moleculer-web\src\index.js:125:20)
at mws.(anonymous function).call.err (\moleculer-web\src\index.js:129:41)
at Array.onfinished (\node_modules\body-parser\lib\read.js:95:9)
at listener (\node_modules\on-finished\index.js:169:15)
at onFinish (\node_modules\on-finished\index.js:100:5)
at callback (\node_modules\ee-first\index.js:55:10)
at IncomingMessage.onevent (\node_modules\ee-first\index.js:93:5)
at IncomingMessage.emit (events.js:160:13)
at endReadableNT (_stream_readable.js:1101:12)
at process._tickCallback (internal/process/next_tick.js:152:19)
code: 413,
type: 'entity.too.large',
data: undefined,
retryable: false }
Request - POST, data - JSON.
Hi all,
I've noticed custom alias handler is not calling the authorize method. First I thought of using onBeforeCall; however, it's not called as well. My temporary solution is to create a custom handler that sets an 'auth' property and creates the Context to invoke the authorize, such as follow:
'POST /files/upload': {
auth: 'required',
handler: async function(req, res) {
const { broker } = req.$service;
const ctx = Context.create(broker, '', broker.nodeID, req.$params, req.$route.callOptions || {});
try {
if (await this.authorize(ctx, req.$route, req)) {
this.uploadFile(req, res);
}
} catch (err) {
this.sendError(req, res, err);
}
},
},
Then, in the authorize method I added the following logic:
// Check if route requires auth
if ((req.$endpoint && req.$endpoint.action.auth === 'required') || (req.$alias && req.$alias.auth === 'required')) {
I guess custom alias/actions should be part of the action lifecycle somehow.
Thanks
Hi,
I may have general usage issue ( due to my ignorace :) ) - so sorry if this question is silly
I have a service action which calls service method which returns a promise ( api call to Twitter )
service action:
user(ctx) {
console.log('Service TW Request >>>>>>>>>>');
return this.Promise.resolve()
.then(() =>{
return this.user()
.then( result => {
this.logger.debug('user method restult', result);
return result;
})
.catch( err => {
this.logger.error('Twitter user error', err)
throw new Error(err);
});
})
}
method:
user(){
this.logger.debug('User method called');
return new Promise((resolve,reject) => {
client
.get('account/verify_credentials')
.then(user => {
this.logger.debug('user results from twitter');
resolve(user);
})
.catch( error => {
reject(new MoleculerError(error));
});
})
}
Issue is that result returned from the method never reaches client - as if client closes connection before the results.
Maybe there are way to many Promises that I'm not handeling to well - again beacuse of my ignorance.
Any help would be greatly apprechiated.
I have also tried without method, directly calling Twitter rest api ( Twitt library ) but with the same result.
service action usertw :
usertw(ctx) {
return client
.get('account/verify_credentials')
.then(user => {
this.logger.debug('usertw results from twitter', user);
return user;
})
.catch( error => {
throw new MoleculerError(error);
});
},
hope you can help
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.