Search code examples
javascriptxmlhttprequestwebhooksgoogle-assistant-sdk

Can't make a XMLHttpRequest inside a Google Action Webhook


I'm trying to teach myself Google Actions, so far so good. My last step to successfully build my project is to use Webhooks to retrieve data from a server.

To do so, I use XMLHttpRequest to send a request to my server, retrieve a JSON data, parse it and make Google Assistant say it out loud.

Here is the code:

const {conversation} = require('@assistant/conversation');
const functions = require('firebase-functions');
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
const app = conversation({debug: true});

app.handle('start_scene_initial_prompt', (conv) => {
  var json = {};
  const xhr = new XMLHttpRequest();
  const url = 'https://myserver.com/getInfo?token=myauthtoken&data=tempRDC';
  xhr.open("GET", url, false);

    try {
        xhr.send();
        if (xhr.status != 200) {
            // we lost connection to mothership
            conv.add('Erreur: '+ xhr.status);
        } else {
            json = JSON.parse(xhr.responseText);
            conv.add('Temperature is ' + json[0].last + '°C');
        }
    } catch (error) {
        conv.add('Unknown error');
    }
});

exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);

The code compiles fine, deploys too, but whatever I do I always end up with "Unknown error":

I also tried an async version, the result is the same :(

const {conversation} = require('@assistant/conversation');
const functions = require('firebase-functions');
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
const app = conversation({debug: true});

app.handle('start_scene_initial_prompt', (conv) => {
    var json = {};
    const xhr = new XMLHttpRequest();
    const url = 'https://nmyserver.com/getInfo?token=myauthtoken&data=tempRDC';
    xhr.open("GET", url, false);
    
    try {
        xhr.send();
        if (xhr.status != 200) {
            // we lost connection to mothership
            conv.add('Erreur: '+ xhr.status);
        } else {
            json = JSON.parse(xhr.responseText);
            conv.add('temperature is ' + json[0].last + '°C');
        }
    } catch (error) {
        conv.add('Unknown error');
    }
});

exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);

I, of course, tested the HTTP request, it works like a charm. I also adapted the code to create something similar but locally, it works too.

Can someone help?


Solution

  • I don't have enough reputation to comment, so I'll put my thoughts here. First of all, XMLHttpRequest is old and outdated. The fetch API is much more reliable and easy. Anyways, back to your code. I think your problem is that you are checking the xhr.status before the response is ready. You're also sending the request before you define a callback. Try using this code instead:

    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
            // Do your logic
        }
    };
    xhr.open("GET", url);
    xhr.send(null);