0
votes

My goal is to insert into bigquery the result of a post request using google cloud function.

My problem is that the cloud function is inserting null values into my table so it's not able to get back the parameters from the post request.

Here is my post request:

<script>
var event_category = 'action';
var event_name = 'click';
var page_url = 'test'
var request = new XMLHttpRequest();
request.open('POST', 'url to my cloud function');
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
        params = {
              event_category: event_category, 
              event_name: event_name, 
              page_url: page_url
              } 
request.send( JSON.stringify(params));
console.log(JSON.stringify(params));
</script>

Code of the google cloud function

const bigquery = require('@google-cloud/bigquery')();
var result = "";

function insertHandler(err, apiResponse) {
  result.writeHead("204",
   "No Content",
   {
     "access-control-allow-origin": "urlofmywebsite",
     "access-control-allow-methods": "GET, POST, OPTIONS",
     "access-control-allow-headers": "content-type, accept",
     "access-control-max-age": 10, // Seconds.
     "content-length": 0
   }
);
return(result.end());
}


exports.loadBQ = function loadBQ (req, res) {
  result = res;
  var dataset = bigquery.dataset("google_analytics_test"); 
  var table = dataset.table("google_tag_manager"); 
  var event_category;
  var event_name;
  var page_url;

  try{
      event_category = req.body.event_category;
      event_name = req.body.event_name;
      page_url = req.body.page_url;
    var row = {
      json: {
        event_category : event_category,
        event_name: event_name,
        page_url: page_url
      }
    };
    var options = {
      raw: true
    };
    table.insert(row, options, insertHandler);
  } catch(e){insertHandler(true, false)};
};

As said earlier the problem reside on reading the post request from the google cloud function , not sure how to unblock that

2

2 Answers

1
votes

Instead of req.body use req.query then pass the variables through the URL like this, for an HTTP event trigger Google Cloud Function https://YOUR_REGION-YOUR_PROJECT_ID.cloudfunctions.net/FUNCTION_NAME?event_category=CATEGORY&event_name=EVENT&page_url=URL

When I was trying to reproduce using your code, the variables were not being assigned, therefore at the end they were undefined, however after modifying req.body to req.query, I was able to get the proper values.

Here is the example code for the Google Cloud Function:

var event_category;
var event_name;
var page_url;

event_category = req.query.event_category;
event_name = req.query.event_name;
page_url = req.query.page_url;

console.log("===VALUES===");
console.log(event_category);
console.log(event_name);
console.log(page_url);

After that you should see the values logged in the Google Stackdrive logging page.

1
votes

There is a way to process an actual POST without having to resort to GET... from https://cloud.google.com/functions/docs/writing/http#writing_http_helloworld-nodejs

const escapeHtml = require('escape-html');

/**
 * Responds to an HTTP request using data from the request body parsed according
 * to the "content-type" header.
 *
 * @param {Object} req Cloud Function request context.
 * @param {Object} res Cloud Function response context.
 */
exports.helloContent = (req, res) => {
  let name;

  switch (req.get('content-type')) {
    // '{"name":"John"}'
    case 'application/json':
      name = req.body.name;
      break;

    // 'John', stored in a Buffer
    case 'application/octet-stream':
      name = req.body.toString(); // Convert buffer to a string
      break;

    // 'John'
    case 'text/plain':
      name = req.body;
      break;

    // 'name=John' in the body of a POST request (not the URL)
    case 'application/x-www-form-urlencoded':
      name = req.body.name;
      break;
  }

  res.status(200).send(`Hello ${escapeHtml(name || 'World')}!`);
};