Home > other >  Google Sheets AppScript - nested try catch in doPost - behaviour depends on method of invocation?
Google Sheets AppScript - nested try catch in doPost - behaviour depends on method of invocation?

Time:06-04

I've got a bound AppScript in Google Sheets that writes some data from a HTML form to the spreadsheet and emails the user the data they submitted.

Everything inside doPost() is wrapped in a try{} catch(){return}, so that there's always a successful HTTP response, even if it's an error message which I display to the user.

And I have a doGet(e) function that calls doPost(e) for debugging purposes.

I've also got a simple function that logs to a sheet (since when doPost is triggered by post data it doesn't record anything from Logger.log()). For reference (though I believe it's irrelevant) I've included my logToSheet code.

I'm attempting to wrap MailApp.sendMail() in a try catch(return) so I can report to the user that writing to the sheet was successful, and just the emailing failed (instead of just that something failed during submission and they should keep trying to submit).

The script is working well with valid data.

Weirdly, when I execute doPost() from the AppScript IDE or by making a GET request using test data with an invalid email address, it works as expected - the script stops in the nested catch, as confirmed by the execution log statements. However, when I trigger the script by POSTing data (even when discarding the POSTed data and using the same test data as when running from GET or the IDE), the script returns from the outer catch, and logs are not properly written to the sheet.

My deployment is up to date, and I'm posting to the correct deployment URL.

Here's my simplified code:

function doGet(e) { //Treat GET requests same as POST's for debugging/testing
  Logger.log('GET request');
  Logger.log(e);
  doPost(e);
}

doPost(ignorePostData) {
try{

// Some test parameters for debugging.
e = {
      parameters: {
        uuid: '60e16d53-9ac1-4bb7-9451-0fe09bfa0c82',
        mobility___2: 'on',
        email: ['oliveil.com'],
        transport___1: 'on',
        allergens___1: 'Gluten, Peanuts',
        meal_type___1: `Children's meal (Under 13)`,
        meal_type___2: `No Meal (Infant)`,
        dietary___1: '',
        rsvp_yesno: 'Yes',
        dietary___2: '',
        mobility___1: 'on',
        guest___1: 'Guest 1 Name',
        allergens___2: 'Gluten',
        transport___2: 'on',
        salt: 'fnw3cz',
        guest___2: 'Guest 2 Name',
        group_name: 'Group Name Here'
      }
    };

logToSheet(e.parameters);

//code to write data to sheet here (which works fine)
//And generate the OPTIONS_OBJECT (which works with a valid email address)

try{
    MailApp.sendEmail(OPTIONS_OBJECT); //Send the email
    }catch (error){
      Logger.log('mail error block');
      logToSheet('mail error block');
      Logger.log(error);
      logToSheet(error.toString());
    return ContentService
      .createTextOutput(JSON.stringify({ "result": "error", "errordetails": error.toString(), "message": "Sorry, something went wrong while sending an email with your RSVP details. Your RSVP has been received successfully though!<br /><br />The error has been logged." }))
      .setMimeType(ContentService.MimeType.JSON);
    }
} catch (error) { // if error return this
  Logger.log('main error block');
    Logger.log(error);
    logToSheet('main error block');
    logToSheet(error.toString());


    return ContentService
      .createTextOutput(JSON.stringify({ "result": "error", "errordetails": error.toString(), "message": "Sorry, something went wrong while processing your submission. Please try again.<br /><br />The error has been logged." }))
      .setMimeType(ContentService.MimeType.JSON);
  }
}

//A simple logging function, since we can't get logs of doPOST without more complex setup
function logToSheet(logString) {
  const doc = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = doc.getSheetByName('logs'); // select the Guest RSVPs sheet
  const data = sheet.getDataRange();
  const nextRow = sheet.getLastRow()   1; // get next row
  const time = new Date().toUTCString();
  sheet.getRange(nextRow, 1, 1, 2).setValues([[time, logString]]);
  
  return;
}

Here's the output when triggering from the IDE or a GET request: AppScript IDE Execution log

spreadsheet log

And result of triggering by POST: Chrome console

Spreadsheet log

Edit: As requested, added my logToSheet() function. I've also tried renaming the error variables in the two catch blocks, so it's not a weird variable scoping issue.

I have a hunch this may be due to asynchronous behaviour...

CodePudding user response:

I'm an idiot. I was editing my scripts.js file and forgot I had switched my site to load the minified file - which was not updating, as I did not have minify on save enabled.

Lesson learned - log the deployment, and archive old deployments while testing.

As usual, when computers aren't repeatable you're either doing something really dumb, or it's some real edge case that requires very low level understanding.

And 99.9% of the time, you're doing something really dumb.

  • Related