I'm trying to implement a custom chat window for a DialogFlow chatbot. AFAIK, I need to create a server to handle requests from the chat window, forward them to DialogFlow for a response, and then return that response to the chat window. I followed the sample from the DialogFlow Node.js client SDK (step 6: "Try an example") and ended up with this:
require('dotenv').config()
const dialogflow = require('dialogflow');
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
app.use(express.json());
const sessionClient = new dialogflow.SessionsClient({
credentials: {
client_email: process.env.CLIENT_EMAIL,
private_key: process.env.PRIVATE_KEY
}
});
async function getResponse(req, res) {
// A unique identifier for the given session
console.log("body", req.body);
const sessionId = req.body.session.split('/').pop();
// Create a new session
console.log("session", sessionId)
const sessionPath = sessionClient.sessionPath(process.env.PROJECT_ID, sessionId);
// The text query request.
const request = {
session: sessionPath,
queryInput: {
text: {
// The query to send to the dialogflow agent
text: req.body.queryResult.queryText,
// The language used by the client (en-US)
languageCode: 'en-US',
}
}
};
console.log("send request", request)
// Send request and log result
const responses = await sessionClient.detectIntent(req);
const result = responses[0].queryResult;
res.json(result);
}
app.post('/', getResponse);
app.get('/', (req, res) => res.send('Use POST'));
app.listen(PORT, () => {
console.log('Server is running on PORT:',PORT);
});
Although the original sample worked, sending a POST request to my server using Postman gives me this error:
(node:724) UnhandledPromiseRejectionWarning: Error: 3 INVALID_ARGUMENT: Resource name '' does not match 'projects/*/locations/*/agent/environments/*/users/*/sessions/*'.
at Object.callErrorFromStatus (C:\Users\rudyt\Documents\Github\metbot-fulfillment\node_modules\@grpc\grpc-js\build\src\call.js:30:26)
at Http2CallStream.call.on (C:\Users\rudyt\Documents\Github\metbot-fulfillment\node_modules\@grpc\grpc-js\build\src\client.js:96:33)
at Http2CallStream.emit (events.js:194:15)
at process.nextTick (C:\Users\rudyt\Documents\Github\metbot-fulfillment\node_modules\@grpc\grpc-js\build\src\call-stream.js:75:22)
at process._tickCallback (internal/process/next_tick.js:61:11)
(node:724) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:724) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
I'm not sure where this error is coming from, whether there's an issue with how I formatted the request in my getResponse function or if somehow it's related to Postman? The query I'm making (on the Postman side) is a POST to http://localhost:3000 with the Content-Type
header set to application/json
and the request body set as raw JSON (I pasted in this sample Webhook request). I'm leaning towards the issue being with the request to DialogFlow but I included the Postman info just in case.
I think the problem is that you're not sending what you think you're sending to detectIntent()
.
Assuming this code is meant to run on a server somewhere, take the request from the JavaScript client, and then create a request to Dialogflow - you're not actually doing that.
Although you are creating the request (in a constant named request
) and logging it
// The text query request.
const request = {
session: sessionPath,
queryInput: {
text: {
// The query to send to the dialogflow agent
text: req.body.queryResult.queryText,
// The language used by the client (en-US)
languageCode: 'en-US',
}
}
};
console.log("send request", request)
when you go to send this to Dialogflow you're not sending the request
object, but rather the req
object, which is what came from the client:
const responses = await sessionClient.detectIntent(req);
You should never pass something from a client without sanitizing it in your server first.
I suspect if you change it to something like this, it should work:
const responses = await sessionClient.detectIntent(request);