0

I have a function that utilizes promises.

I've executed the code via https.onRequest() and it writes to the database, however, when I use the same code on a document().onCreate() it just abruptly stops and I receive a message in the function logs "Ignoring exception from a finished function" with no other log entries.

The code stops executing after the comment "//server status code". In the console, I see the voter response JSON from the server followed by the status code. I've tried to use the collection().doc().set() and .add(). Earlier in the logs, I receive a "Function returned undefined, expected Promise or value" error, which I don't get in the https.onRequest(). The code is identical with the exception on the .onCreate() code pulling some additional information from the database at the start.

Any help would be greatly appreciated.

const functions = require('firebase-functions');

const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

exports.testonupdate = functions.firestore.document("users/{userId}/voterRegistration/infoToSubmit").onCreate((snap, context) => {
console.info('New voter info has been added to check verification')
const voterValues = snap.data();
console.info('database values: ' + voterValues);
const voterInfo = {
    'firstName': voterValues.firstName,
    'lastName': voterValues.lastName,
    'dob': voterValues.dob,
    'street': voterValues.street,
    'city': voterValues.city,
    'zip': voterValues.zip
}
const userID = voterValues.userId
console.info('voter info values: ' + voterInfo + userID) 

var request = require('request');
var jar = request.jar();
var voteUrl = 'https://'
var utahApi = 'https://'
var xsrfOptions = {
    url: voteUrl,
    method: 'get',
    jar: jar
};
// initial promise
var options = new Promise((resolve, reject) => {
    request.get(xsrfOptions, () => {
        var fullCookie = jar.getCookies(voteUrl);
        resolve(fullCookie);

    })
})

options.then((value) => {
    //parse cookie returned from var options and dump into headers
    var cookieToString = value.toString()
    var xsrfCookie = cookieToString.slice(0, 47)
    var slicedCookie = cookieToString.slice(11, 47)
    console.info('slicedCookie :' + slicedCookie)
    //POST request data
    return {
        uri: utahApi,
        headers: {
            'Host': 'votesearch.utah.gov',
            'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:66.0) Gecko/20100101 Firefox/66.0',
            'Accept': 'application/json, text/plain, */*',
            'Accept-Language': 'en-US,en;q=0.5',
            'Accept-Encoding': 'gzip, deflate, br',
            'Referer': voteUrl,
            'Content-Type': 'application/json;charset=utf-8',
            'X-XSRF-TOKEN': slicedCookie,
            //'Content-Length': '300', LEAVE THIS COMMENTED OUT OR SERVER WILL NOT RESPOND
            'Connection': 'keep-alive',
            'Cookie': xsrfCookie,
            'Pragma': 'no-cache',
            'Cache-Control': 'no-cache'
        },
        method: 'POST',
        json: true,
        //user info goes here
        body: {
            'firstName': voterValues.firstName,
            'lastName': voterValues.lastName,
            'dob': voterValues.dob,
            'street': voterValues.street,
            'city': voterValues.city,
            'zip': voterValues.zip
        }
    }
}).then((options) => {
    console.info('starting request...')
    // voter registration request
    request(options, (error, response, body) => {
        if (!error && response.statusCode === 200) {
            console.info(response.body.voter); // voter response
            console.info(response.statusCode); // server status code
            admin
                .firestore()
                .collection("users")
                .doc("userID")
                .set(response.body);


        } else {
            console.info('failed response code ' + response.statusCode);
            console.info('failed at retreiving voterInfo ' + error);

        }
    });
    // return console.info('did we finish?')
    //catch any error messages
}).catch((err) => {
    console.info('errored at end of function: ' + err);
})


})
Onyoursix
  • 109
  • 9
  • Can i have your cloud function code..? – Dev May 11 '19 at 22:57
  • I've posted all my code, I only took out a couple of links for the API I'm hitting. – Onyoursix May 11 '19 at 23:05
  • I forgot to add the code at the top of my index.js firebase functions file - added that. – Onyoursix May 11 '19 at 23:16
  • So, just an update, if I add `return` in front of `options.then`... then all the error messages go away, however, it still fails to write to the database. I see the voter information being pulled, same as before, but nothing writes to firestore. `return options.then((value) => {.....` – Onyoursix May 11 '19 at 23:58
  • 1
    You're not returning a promise that resovles when all the asynchronous work is done in your function. You leave promises dangling, – Doug Stevenson May 12 '19 at 04:22
  • If you want, from a Cloud Function, to call an external API you need to use a library like request-promise (https://github.com/request/request-promise). See https://stackoverflow.com/questions/52526521/google-cloud-functions-call-url-hosted-on-google-app-engine/52526632#52526632 or https://stackoverflow.com/questions/54275148/how-to-fetch-a-url-with-google-cloud-functions-request/54276070#54276070 for some examples – Renaud Tarnec May 12 '19 at 09:47

1 Answers1

0

Creating a new promise for request(options, (error, response, body) => {..... seemed to fix the issue.

Onyoursix
  • 109
  • 9