我正在使用Firebase Cloud功能进行DialogFlow项目。 我向我的API发送GET请求,然后从服务器接收回数据,然后在实现文本属性中显示它。很好。
现在,我需要将服务器的cookie会话ID存储在某种“应用程序变量”中,以便跟踪客户端和服务器之间的交互。 我尝试将Cookie会话保存在Context对象中,这样做会出现错误:
Agent.getContext不是IncomingMessage.resp的函数
代码如下:
exports.dialogflowFirebaseFulfillment = functions.https.onRequest( ( req, resp ) =>{
const agent = new WebhookClient( {request: req, response: resp} );
//SET CONTEXT HERE
const context = {
'name': 'sessione',
'lifespan': 2,
'parameters': {'idSessione': c.sessionID}
};
agent.setContext( context );
if( context ){
console.log( '*--*****************-- name context =' + context.name );
}
//...some stuff etc-
//call my function to consume API
callAVA( strRicerca ).then( ( strOutput ) =>{
return resp.json( {'fulfillmentText': strOutput} );
} ).catch( ( error ) =>{
return resp.json( {'fulfillmentText': 'error error'} );
} );
} );
// added parameter Agent-
function callAVA( agent, strRicerca ){
return new Promise( ( resolve, reject ) =>{
https.get( options, ( resp ) =>{
//variable options contains set cookies values , host name etc-
let data = '';
// A chunk of data has been recieved.
resp.on( 'data', ( chunk ) =>{
data += chunk;
} );
// The whole response has been received. Print out the result.
resp.on( 'end', () =>{
let c = JSON.parse( data );
let strOutput = c.output[0].output;
console.log( '----- ID DELLA SESSIONE : ' + c.sessionID );
if( c.sessionID ){
// I NEED TO SAVE IDSESSION FROM SERVER -
let context = agent.getContext( 'sessione' );
// GOT ERROR: agent.getContext is not a function at IncomingMessage.resp (????)
context.parameters.idSessione = c.sessionID;
}
resolve( strOutput );
//DO OTHER STUFF...
} );
resp.on( "error", ( err ) =>{
console.log( "Error: " + err.message );
reject( err.message );
} );
} );
} );
}
还有其他方法可以跟踪向服务器发送请求的用户吗?我宁愿保持简单而不访问数据库...非常感谢,我们将不胜感激。 :)
__________________________________编辑________________________________ 暂时搁置上下文,我意识到我遗漏了一些要点,因此 我已根据您的建议修改了我的代码,如下所示:
const functions = require('firebase-functions');
const querystring = require('querystring');
const {WebhookClient} = require('dialogflow-fulfillment');
const https = require('http');
postData = querystring.stringify({
'searchText': 'ciao',
'user':'',
'pwd':'',
'ava':'FarmaInfoBot'
});
const options = {
hostname: '86.107.98.69',
port: 8080,
path: ‘/mypath/search_2?searchText=',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(postData),
'Cookie':'JSESSIONID=' // -> this comes from the server, store it in context, conv.data or what else-> to do
}
};
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((req, resp) => {
const agent = new WebhookClient({ request: req, response: resp});
let strRicerca='';
if (req.body.queryResult.parameters['searchText']) {
strRicerca=req.body.queryResult.parameters['searchText'];
options.path+=strRicerca+'&user=&pwd=&ava=FarmaInfoBot';
}
/* IS THIS OK NOW TO INVOKE FUNCTION LIKE THIS, NOW THAT I ADDED AGENT ? */
callAVA(agent, strRicerca).then((strOutput)=> {
return resp.json({ 'fulfillmentText': strOutput });
}).catch((error) => {
return resp.json({ 'fulfillmentText': 'error!!!!!!!!!!'});
});
function callAVA(agent, strRicerca) {
return new Promise((resolve, reject) => {
https.get(options, (resp) => {
let data = '';
console.log(`STATUS RESPONSE: ${resp.statusCode}`);
console.log(`HEADERS RESPONSE: ${JSON.stringify(resp.headers)}`);
resp.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
var c=JSON.parse(chunk);
});
resp.on('end', () => {
let c=JSON.parse(data);
let strOutput= agent.add('Static response from Agent'); // c.output[0].output;
console.log(strOutput);
resolve(strOutput);
});
resp.on("error", (err) => {
console.log("Error: " + err.message);
reject(err.message);
});
});
});
}
let intentMap = new Map();
intentMap.set('test_fb', callAVA);
agent.handleRequest(intentMap);
});
现在程序正在运行,但是我收到一个空响应,崩溃发生在结束事件中,解析了Json数据。 我的最终目的是找到一种方法,将来自服务器的cookie保存在一个全局变量中,并在整个对话过程中保持它。
答案 0 :(得分:2)
这里似乎有一些问题。
错误的直接原因是您将callAVA()
函数定义为
function callAVA( agent, strRicerca )
但是当您在前面几行调用它时,您将忽略agent
参数:
callAVA( strRicerca )
但是,从长远来看,您的使用方式还有其他问题。
虽然您所做的工作可能是有效的并且可能有效,但它与处理通常的工作方式也有所不同,并且可能是您为此造成了一些问题。
通常,根据需要创建agent
,然后针对它注册Intent Handlers。像
let intentMap = new Map();
intentMap.set('intent.name.1', intentHandlerFunction1);
intentMap.set('intent.name.2', intentHandlerFunction2);
agent.handleRequest(intentMap);
,它将使用单个参数agent
调用Intent名称的匹配函数。 (顺便说一句-好工作,回报了承诺!您的那部分正确。)
作为Intent处理程序的一部分,您需要在Promise完成之前调用agent.setContext(context)
。在以后的Intent处理程序中,当您想知道该值时,需要调用agent.getContext('context-name')
,该方法应返回整个Context对象,包括剩余寿命和该对象的参数。
更新
您在第一次编辑中所做的更改还不够。问题在于您正在混合两种不同的方式来调用Intent处理程序:
以一种方式,您可以使用第二个参数直接调用它。作为结果的一部分,它将向resp
对象发送JSON。
以另一种方式,您已经向intentMap.set()
注册了它,这导致它在调用agent
时被调用(仅使用handleRequest()
参数)正在通过agent
对象设置响应。
通常,除非您想自己操纵所有JSON,否则应依靠方法(2)。您应该不直接自己调用Intent Handler函数,而是让handleRequest()
为您处理它。
由于您需要strRicerca
对象,因此可以在函数运行所在的范围内使该对象可用,它似乎已经存在。因此,您可能不需要将其作为参数。