0
votes

I am using Google Apps Script to make a UrlFetchApp call to a node.js API endpoint. I own both the Google Apps Script code and node.js code & endpoint, so I can watch what is happening.

When I use Postman, it works. But when I use GAS UrlFetchApp, it doesn't work, as req.body in node is empty { }. I even looked at the code that Postman creates for JavaScript Fetch and try to nearly duplicate it, except for things I know GAS' UrlFetchApp needs. I've done quite a few UrlFetchApp calls with GAS to various external endpoints. So, I'm not new, but can't figure this one out.

Here is my Google Apps Script code:

    var url = 'https://xxxxxxxxxxx.azurewebsites.net/api/account';

    var data = {
      "email": address,
      "apiKey": 'xxxxxxxxxxxxxxxxxxx'
    }

    var payLoadInfo = JSON.stringify(data);

    var options = {
      "method": "GET",
      "headers": {'Content-Type': 'application/json'},
      // 'Content-Type': 'application/json',
      // "contentType": 'application/json',
      redirect: 'follow',
      "muteHttpExceptions": true,
      "body": payLoadInfo,
      // "payload": JSON.stringify(data)
      // payload: payLoadInfo
    };

    var response = UrlFetchApp.fetch(url, options);

The commented out parts of "options" are several different ways I've tried to get it to work. I know in the past that I've usually used "payload" instead of "body" like I am this time (Postman suggested it). When I use "payload", it fails completely, not even getting to my node code. I also tried putting the apiKey in the header.

Here is the node.js API endpoint code:

  router.get("/account", async (req, res) => {

  var apiKey = process.env.API_KEY;

  console.log('apiKey = ' + apiKey);
  console.log('req.body = ' + JSON.stringify(req.body, null, 2));
  console.log('req.body.apiKey = ' + req.body.apiKey);

  if (req.body.apiKey != apiKey) {

    console.log('apiKey is not equal');
    res.status(401).send({ error: "You are not authorized." });

  } else {

    process the request...

  }

When I use "payload" in "options" I get a 500, and the server code never executes. When I use "body" in "options", I see the server code execute, but the console.log('req.body = ' + JSON.stringify(req.body, null, 2)), just comes back with an empty object {}, and then since req.body.apiKey != apiKey, it consoles "apiKey is not equal" and sends a 401. When using Postman, the req.body object consoles fine, showing the email & apiKey.

No matter what combinations of things I put into options, it fails either with 500 or 401. However, Postman works great with pretty much the same parameters, headers, etc.

Here is what Postman shows for the code:

var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Cookie", "ARRAffinity=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ARRAffinitySameSite=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");

var raw = JSON.stringify({"email":"[email protected]","apiKey":"xxxxxxxxxxxxxxxx"});

var requestOptions = {
  method: 'GET',
  headers: myHeaders,
  body: raw,
  redirect: 'follow'
};

I even tried including the cookie and "redirect: follow", but none works.

What am I missing?

1
What is the script of Here is what Postman shows for the code:?Tanaike
@Tanaike The code shown is what Postman produced for the same identical JavaScript fetch request to the node.js endpoint that I'm trying to do from Google App Script via URLFetchApp.Chris
Thank you for replying. If the script of Here is what Postman shows for the code: is Javascript, I think that the script cannot be used. I'm worry about this. For example, when your postman sample worked, can you export it as the curl sample? And, I thought that req.body might be used for the POST method. How about this?Tanaike
Thank you for replying. For exmple, when you want to use router.get("/account", the endpoint might be https://###/account?email=###&apiKey=### using the query parameters. And you can retrieve the values of query parameters as console.log(req.query). How about this?Tanaike
Thank you for replying. When you want to include the api key in the request header, you can retrieve it by req.headers at the server side.Tanaike

1 Answers

0
votes

I got it to work, thanks to help from @Tanaike (see comments above).

It seems that unlike normal "fetch" in node.js, URLFetchApp in Google Apps Script will not send a body along with a GET.

I still used GET, but changed to sending the param in the URL and the apiKey in the header.