moleculerjs / moleculer-web

:earth_africa: Official API Gateway service for Moleculer framework
http://moleculer.services/docs/moleculer-web.html
MIT License
291 stars 118 forks source link

BodyParse Converting circular structure to JSON in production mode #220

Closed baenacoco closed 3 years ago

baenacoco commented 3 years ago

Prerequisites

Please answer the following questions for yourself before submitting an issue.

Current Behavior

Example code:

xmlExample: {
    rest: {
        method: "POST",
        path: "/xml/example",
        type: "stream",
    },
    async handler(ctx) {
        return ctx.params.body;
    },
}

Expected Behavior

I expected to get the same XML in the petition.

Failure Information

Please view the logs.

Steps to Reproduce

Please provide detailed steps for reproducing the issue.

  1. moleculer init project moleculer-demo
  2. add greater.service.js
    xmlExample: {
    rest: {
        method: "POST",
        path: "/xml/example",
        type: "stream",
    },
    async handler(ctx) {
        return ctx.params.body;
    },
    }
  3. add bodyParser in api.service.js
    text: {
    type: "application/xml",
    },
  4. npm run dc:up and check with postman or a preferred desktop API client. image

Context

Please provide any relevant information about your setup. This is important in case the issue is not reproducible except for under certain conditions.

Failure Logs

api_1               | [2020-12-11T17:31:31.088Z] ERROR 4cb49354fbc8-20/API:    Request error! TypeError : Converting circular structure to JSON
api_1               |     --> starting at object with constructor 'Socket'
api_1               |     |     property 'parser' -> object with constructor 'HTTPParser'
api_1               |     --- property 'socket' closes the circle 
api_1               |  TypeError: Converting circular structure to JSON
api_1               |     --> starting at object with constructor 'Socket'
api_1               |     |     property 'parser' -> object with constructor 'HTTPParser'
api_1               |     --- property 'socket' closes the circle
api_1               |     at JSON.stringify (<anonymous>)
api_1               |     at JSONSerializer.serialize (/app/node_modules/moleculer/src/serializers/json.js:36:27)
api_1               |     at NatsTransporter.serialize (/app/node_modules/moleculer/src/transporters/base.js:339:33)
api_1               |     at NatsTransporter.publish (/app/node_modules/moleculer/src/transporters/base.js:191:21)
api_1               |     at NatsTransporter.prepublish (/app/node_modules/moleculer/src/transporters/base.js:325:15)
api_1               |     at Transit.publish (/app/node_modules/moleculer/src/transit.js:1158:18)
api_1               |     at Transit._sendRequest (/app/node_modules/moleculer/src/transit.js:763:15)
api_1               |     at /app/node_modules/moleculer/src/transit.js:706:53
api_1               |     at new Promise (<anonymous>)
api_1               |     at Transit.request (/app/node_modules/moleculer/src/transit.js:706:10) 
api_1               | Data: undefined
icebob commented 3 years ago

You can't send the request as a stream because the POST body stream is processed by the text body parser. And because the body is not an object, you should use mergeParams: false in route options:

greeter.service.js

        xmlExample: {
            rest: {
                method: "POST",
                path: "/xml/example",
                //type: "stream",
            },
            async handler(ctx) {
                return ctx.params.body;
            },
        }

route options in api.service

                bodyParsers: {
                    json: {
                        strict: false,
                        limit: "1MB"
                    },
                    urlencoded: {
                        extended: true,
                        limit: "1MB"
                    },

                    text: {
                        type: "application/xml",
                    },
                },

                mergeParams: false,

                // Mapping policy setting. More info: https://moleculer.services/docs/0.14/moleculer-web.html#Mapping-policy
                mappingPolicy: "all", // Available values: "all", "restrict"

Result: image