0

I have a question about http request on Dialogflow's Fulfillment. I want to make http POST request from Dialogflow to another web DB service.

But 2 errors occured. If you know the solution, could you please tell me?

FYI, I tested http post request itself on Postman and Node.js local file, then the request completed successfully.

  1. Request timeout error

      "status": {
        "code": 206,
        "errorType": "partial_content",
        "errorDetails": "Webhook call failed. Error: Request timeout.",
        "webhookTimedOut": true
      }
  2. ENOTFOUND error

{ Error: getaddrinfo ENOTFOUND <service url> <service url>:443
    at errnoException (dns.js:28:10)
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:76:26)
  code: 'ENOTFOUND',
  errno: 'ENOTFOUND',
  syscall: 'getaddrinfo',
  hostname: '<service url>',
  host: '<service url>',
  port: 443 
}

The code I edited in Fulfillment's 'Inline Editor' is below.

(function() {
    'use strict';

    // Cloud Functions for Firebase library
    const functions = require('firebase-functions');
    // Google Assistant helper library
    const DialogflowApp = require('actions-on-google').DialogflowApp;
    const googleAssistantRequest = 'google';
    const req = require('request');

    function addTask(request, response) {

        let action = request.body.result.action;
        let parameters = request.body.result.parameters;
        let inputContexts = request.body.result.contexts;
        let requestSource = (request.body.originalRequest) ? request.body.originalRequest.source : undefined;
        const app = new DialogflowApp({request: request, response: response});

        // Function to send correctly formatted Google Assistant responses to Dialogflow which are then sent to the user
        function sendGoogleResponse(responseToUser) {
            if (typeof responseToUser === 'string') {
                app.ask(responseToUser);
            } else {
                // If speech or displayText is defined use it to respond
                let googleResponse = app.buildRichResponse().addSimpleResponse({
                    speech: responseToUser.speech || responseToUser.displayText,
                    displayText: responseToUser.displayText || responseToUser.speech
                });

                if (responseToUser.googleRichResponse) {
                    googleResponse = responseToUser.googleRichResponse;
                }

                if (responseToUser.googleOutputContexts) {
                    app.setContext(...responseToUser.googleOutputContexts);
                }

                // Send response to Dialogflow and Google Assistant
                app.ask(googleResponse);
            }
        }

        // Function to send correctly formatted responses to Dialogflow which are then sent to the user
        function sendResponse(responseToUser) {
            // if the response is a string send it as a response to the user
            if (typeof responseToUser === 'string') {
                let responseJson = {};
                responseJson.speech = responseToUser;
                responseJson.displayText = responseToUser;
                // Send response to Dialogflow
                response.json(responseJson);
            } else {
                // If the response to the user includes rich responses or contexts send them to Dialogflow
                let responseJson = {};

                // If speech or displayText is defined, use it to respond (if one isn't defined use the other's value)
                responseJson.speech = responseToUser.speech || responseToUser.displayText;
                responseJson.displayText = responseToUser.displayText || responseToUser.speech;
                responseJson.data = responseToUser.richResponses;
                responseJson.contextOut = responseToUser.outputContexts;

                // Send response to Dialogflow
                response.json(responseJson);
            }
        }

        const actionHandlers = {
            'input.firstquestion': () => {
                const headers = {
                    'Content-Type': 'application/json'
                };

                const form = {
                    'app': 503,
                    'record': {
                        'todo': {
                            'value': parameters.task
                        },
                        'duedate': {
                            'value': parameters.date
                        }
                    }
                };

                const options = {
                    url: '<service url>',
                    method: 'POST',
                    headers: headers,
                    json: form
                };

                req(options, function(error, resp, body) {
                    if (body) {
                        console.log(body);
                    } else if (error) {
                        console.log(error);
                    }
                });
            },
            'default': () => {
                // Use the Actions on Google lib to respond to Google requests; for other requests use JSON
                if (requestSource === googleAssistantRequest) {
                    let responseToUser = {
                        speech: 'これはDialogflowからのメッセージです',
                        text: 'これはDialogflowからのメッセージです'
                    };
                    sendGoogleResponse(responseToUser);
                } else {
                    let responseToUser = {
                        speech: 'これはDialogflowからのメッセージです',
                        text: 'これはDialogflowからのメッセージです'
                    };
                    sendResponse(responseToUser);
                }
            }
        };

        if (!actionHandlers[action]) {
            action = 'default';
        }

        actionHandlers[action]();
    }

    exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
        console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
        console.log('Dialogflow Request body: ' + JSON.stringify(request.body));
        if (request.body.result) {
            addTask(request, response);
        } else {
            console.log('不正なリクエストです');
            return response.status(400).end('不正なWebhookのリクエストです。v1かv2のWebhookリクエストを利用してください。');
        }
    });
})();
Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
Tomosuke
  • 1
  • 1
  • code snippets not good here, they are meant for standalone code, yours cant be just run – Mixone Jan 15 '18 at 02:38
  • @Doug Stevenson Thanks for your comment. I am now developing Google Home conversation by Dialogflow. Does it mean that I can't use http request from Google Home to another services for free plan? – Tomosuke Jan 15 '18 at 04:18
  • The request isn't coming "from" Google Home. It's coming "from" Cloud Functions. You're bound to the constraints of the Cloud Functions for Firebase free plan until you upgrade to Blaze. – Doug Stevenson Jan 15 '18 at 04:28
  • Thanks for your reply. I understand that I have to upgrade if I want to make requests to another services without Google related services. Or I choose to make functions on another server(AWS etc.) and set webhook url on Fulfillment's Webhook category. – Tomosuke Jan 15 '18 at 04:53
  • Finally I made it on Blaze plan. Thanks for your advice! – Tomosuke Jan 15 '18 at 06:31

0 Answers0