GithubHelp home page GithubHelp logo

moleculerjs / moleculer-web Goto Github PK

View Code? Open in Web Editor NEW
292.0 16.0 119.0 3.12 MB

:earth_africa: Official API Gateway service for Moleculer framework

Home Page: http://moleculer.services/docs/moleculer-web.html

License: MIT License

JavaScript 99.88% HTML 0.12%
api-gateway microservices moleculer http-server gateway hacktoberfest

moleculer-web's People

Contributors

0x0a0d avatar alebertacco avatar andree-parakey avatar andremaz avatar ariesclark avatar daniel-parakey avatar dependabot[bot] avatar donvietnam avatar dsanel avatar edgardoalz avatar emiljanitzek avatar filiafobico avatar hwuethrich avatar icebob avatar intech avatar kechkibet avatar machinaexdeo avatar mariusbackes avatar michaelermer avatar molobala avatar moonrailgun avatar mtiller avatar ngraef avatar nicklasfrahm avatar richardgarnier avatar rmccallum81 avatar rolandpaltz avatar thib3113 avatar tobydeh avatar yartash avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

moleculer-web's Issues

Missing dependency

Hi!

chalk is missing in package.json, because of this, the use of moleculer-web as a dependency with npm install --production is impossible.

Cors with multiple origins returning error

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:

moleculer-web/src/index.js

Lines 922 to 925 in 08cdc3c

} else if (Array.isArray(route.cors.origin)) {
res.setHeader("Access-Control-Allow-Origin", route.cors.origin.join(", "));
res.setHeader("Vary", "Origin");
}

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

ctx.meta.$responseStatus not working

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?

Multi route does not work properly

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 new action/service without restart

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

404 when using aliases & cors

Problem

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',
}

upload files and REST

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

Service with express not working

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();

Use meta for response headers, contentType, statusCode...etc

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 response
  • ctx.meta.$responseHeaders - set custom response headers
  • ctx.meta.$responseStatus - set HTTP status code in response
  • ctx.meta.$location - redirect location when the $responseStatus is 3xx

Example

{
    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();
    }
}

HTTP 2 support

Hello,
I would like add a request for enhancement HTTP 2 support protocol
Congratulations for this framework!

Enable force https redirect

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.

Before setting Content-Type header, check to see if it's not already set

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.

Error handling middleware causes Timeout Errors

Summary

When using error handling middleware as described in the documentation a RequestTimeoutError is raised.

How to reproduce

Clone this repo and cd into it. The repo contains a standard moleculer project with an api service. The api service includes two middlewares:

  • One that simulates a middleware error
  • One that is supposed to handle the error

Run docker-compose up and then curl http://localhost:3000/api/greeter/hello

Expected

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: 

Actual Result

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

Deep Dive

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.

Possible solutions:

Do not suggest to use service middleware for early request termination.

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.

Racing against middleware

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.

Adapt architecture

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.

assets not work

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

Send 503 instead of 404 when service is registered in routes

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.

Proposal:

Send a 503 if the service exists in the route whitelist/aliases

Current hack to make this work (typescript & whitelist & first routes only)

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;
  }
}

Missing ctx.params when have 2 routes

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?

Failed to download repo from 'moleculerjs/moleculer-template-project'!

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'!

Middleware - context object

Since route middlewares signature is this : function(req, res, next) {...} , I wondered how to access the ctx object and add meta data to it

CORS not working

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?

Ability to add CORS settings for routes

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

404 should be returned instead of 501 for ServiceNotFoundError

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

What is the preferred way of sending errors to the api gateway?

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?

Default URI is always accessible

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

    • POST
  • /api/main/test/greeter/create

    • GET
    • POST
    • DELETE
    • PUT
    • ...

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

Add GraphQL support to the API Gateway, with ability to consolidate responses from multiple services, bases on the GraphQL schema definition.

Always 500 as error code

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

const error = new MoleculerError(err.message, err.status, err.type);

Because there you are creating a new MoleculerClientError and passing 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.

Route params

Handle params in aliases "GET posts/:id": "posts.get" and set ctx.params.id

Request Timeout on Webpack as a Service

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 ?

Schema Validator Error.

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.

REST shorthand in aliases

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"				
}

Missing Error Handler on aliasHandler

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));
},

Molecular-web framework is not consuming distributed tracing request headers passed from an external web service.

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;
.
.
.

Service not found

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

How do I change the maximum size of a request?

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.

Custom alias do not call authorize

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

Question: service result not retuned to client

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.