3

I'm sending a POST request to a HTTP Firebase Cloud Function endpoint which contains the following body:

{
  "securityContext": "edbsne0f17660e9ab49ad9bc3ddd4656230e0a9304bd15916f595b793da9109e1f7aa61e76c4afa91319011a7259b24ed583302334e22c5544c4e00506cf2fed93b28434e4088b22dda02712adf63bb6a370f",
  "event": "onInstall",
  "orgId": "7001935574",
  "dc": "AU"
}

But when I try to access any of those properties it shows undefined. The entire body is also undefined.

This is what my onRequest HTTP Cloud Function endpoint looks like. It also shows my other failed attempts of getting the body data, which I have commented out:

export const getZohoDeskCallBack = functions.https.onRequest((req, res) => {

  const body = req.body;
  functions.logger.info('body', body);

  const rawBody = req.body;
  functions.logger.info('rawBody', rawBody);

  // Other attempt 1:
  // const bodySecurityContext = req.body.securityContext;
  // functions.logger.info('bodySecurityContext', bodySecurityContext);

  // Other attempt 2:
  // const rawBodySecurityContext = req.rawBody.securityContext;
  // functions.logger.info('rawBodySecurityContext', rawBodySecurityContext);

  // Other attempt 3:
  // const reqBodyToJSON = req.body.toJSON();
  // functions.logger.info('req.body.toJSON()', reqBodyToJSON);

  // Other attempt 4:
  // const reqRawBodyToJSON = req.rawBody.toJSON();
  // functions.logger.info('req.rawBody.toJSON()', reqRawBodyToJSON);

  // Other attempt 5:
  // const reqBodyToJSONparse = JSON.parse(req.body);
  // functions.logger.info('reqBodyToJSONparse', reqBodyToJSONparse);

  // Other attempt 6:
  // const reqRawBodyToJSONparse = JSON.parse(req.rawBody);
  // functions.logger.info('reqRawBodyToJSONparse', reqRawBodyToJSONparse);

  // Other attempt 7:
  // const reqBodyToJSONparse = req.body.toString();
  // functions.logger.info('reqBodyToJSONparse', reqBodyToJSONparse);

  // Other attempt 8:
  // const reqRawBodyToJSONparse = req.rawBody.toString();
  // functions.logger.info('reqRawBodyToJSONparse', reqRawBodyToJSONparse);

  // Other attempt 9:
  // const reqBodyToJSONparse = req.body.toString();
  // const securityContext = reqBodyToJSONparse.securityContext;
  // functions.logger.info('securityContext', securityContext);

  res.end();
});

You can see a test of the POST request here and here.

Apparently, if a request has a content-type of application/json Firebase Cloud Functions will automatically parse the JSON and put it into the body property.

But as you can see from those tests linked above the header content-type is empty or missing. Also I am unable to change the POST request because I have no control over that.

Maybe that could be the issue? If so, I thought I could access it from the rawBody property, but that also doesn't work.

I have been pulling my hair out trying to solve this. Any help would be much appreciated.

TinyTiger
  • 1,801
  • 7
  • 47
  • 92

1 Answers1

2

Apparently, if a request has a content-type of application/json Firebase Cloud Functions will automatically parse the JSON and put it into the body property.

That's because you do need to add the Content-Type header and Firebase use the appropriate parser for that request. For more information on the libraries that Firebase uses, checkout the documentation.

You can use the body parser middleware and force parse the body as JSON as shown below:

import * as functions from "firebase-functions/v1";
import * as express from "express";
import * as bodyParser from "body-parser";

const app = express();

const parseJsonMiddleware = bodyParser.json({
  type(req) {
    return true;
  },
});

app.post("/getZohoDeskCallBack", parseJsonMiddleware, (req, res) => {
  const body = req.body;
  console.log("body", body);

  const rawBody = req.body;
  console.log("rawBody", rawBody);

  res.end();
});

export const api = functions.https.onRequest(app);

You'll have to update your webhook URL as this will add /api in the URL like this:

POST https://[FUNCTIONS_URL]/api/getZohoDeskCallBack
Dharmaraj
  • 47,845
  • 8
  • 52
  • 84
  • Thanks for this! I'm using TypeScript, and `type(req)` inside `parseJsonMiddleware` is giving me the error: `'req' is declared but its value is never read. ts(6133)`. What exactly does this part do? And how to solve that error? – TinyTiger Jun 01 '22 at 23:41
  • Adding to the above comment, I know from reading the body-parser docs that the `type` option is used to determine what media type the middleware will parse. But I don't understand how it is used in your code, or how to avoid the TypeScript error. – TinyTiger Jun 01 '22 at 23:55
  • 1
    @TinyTiger that `type` can be a function as in my answer. From the docs, ". If a function, the type option is called as fn(req) and the request is parsed if it returns a truthy value.". We are always returning true so it'll always parse the body as JSON. For the TS issues, can you just remove the `req` parameter from the function and try? If that doesn't work try using `//@ts-ignore` for that line once. – Dharmaraj Jun 02 '22 at 03:40