'KoaJs cant handle POST requests on CloudFunctions

I have a NodeJS Application written in KoaJS,

app.ts

const app = new Koa();

app.use(healthCheck());
app.use(bodyParser());
app.use(errorHandler());
app.use(endpoints);

export default app;

main.ts

const port = process.env.PORT || 3000;

if (!isCloudFunctions()) {
    app
        .listen(port, () => {
            console.info(`Listening at http://localhost:${port}`);
        })
        .on('error', console.error);
}

export const api = (req, res) => {
    app.callback()(req, res);
}

The app works well on Cloud Runs, I can deploy the app on Cloud Functions, but on Functions the app can only handle GET requests. If I try a POST request, I get this error

InternalServerError: stream is not readable
at getRawBody (/workspace/node_modules/raw-body/index.js:112:10)
at readStream (/workspace/node_modules/raw-body/index.js:178:17)
at AsyncFunction.module.exports [as json] (/workspace/node_modules/co-body/lib/json.js:39:21)
at executor (/workspace/node_modules/raw-body/index.js:113:5)
at parseBody (/workspace/node_modules/koa-bodyparser/index.js:100:26)
at new Promise (<anonymous>)
at bodyParser (/workspace/node_modules/koa-bodyparser/index.js:85:25)
at next (/workspace/node_modules/koa-compose/index.js:42:32)
at /workspace/webpack:/sample-explore/apps/sample-api/src/middlewares/health-check.ts:10:12
at Generator.next (<anonymous>)

I re-created the application in ExpressJS, and it works fine with both Runs and Functions

However I am really like the native async/await , compose routing of KoaJS

Does anyone know the reason why KoaJS can not handle POST requests on Cloud Functions?



Solution 1:[1]

The json body is automatically parsed in google cloud functions (documentation) and the koa-bodyparser middleware can't handle already parsed bodies.

More info on this issue: https://github.com/koajs/bodyparser/issues/127

Suggested fixes, from the issue thread, are to either use ctx.req.body instead of ctx.request.body, you'll need to parse it when running locally of course. Alternatively add a middleware that will support already parsed bodies.

function hybridBodyParser (opts) {
  const bp = bodyParser(opts)
  return async (ctx, next) => {
    ctx.request.body = ctx.request.body || ctx.req.body
    return bp(ctx, next)
  }
}

app.use(hybridBodyParser())

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 TetsuBo