Botframework-sdk: [nodejs] Using LuisDialog behind a Proxy

Created on 1 Jun 2016  路  10Comments  路  Source: microsoft/botframework-sdk

I'm trying to use a Luis DIalog in an environment where I have a proxy to go out to external URLs like luis.ai URL. When I try to use it the LuisDialog with the LuisURL inside my nodejs application it gets stucked because I need to provide it the proxy URL and the authentication but I cannot find any way to do that.

How can I do this?

Thx!

bug

Most helpful comment

Hi @Stevenic, I finally find a solution for this problem. Maybe this helps you if anyone or any company face the same problem.

We use the global-tunnel module to force the connections to go through the proxy. It uses the environment variable http_proxy and https_proxy, so you can easily use it, like you can see here:

var globalTunnel = require('global-tunnel');

process.env.http_proxy = 'http://proxy:80';
process.env.https_proxy = 'http://proxy:80';
globalTunnel.initialize();

Then you only have to initialize it before you instantiate the LuisDialog and you even can then close the proxy connection and be using your "normal" connection as you can see here:

var dialog = new builder.LuisDialog('https://api.projectoxford.ai/luis/v1/application?id=bb3b52f7-ba5a-4358-9b16-0a321fc4bc10&subscription-key=XXXX');
globalTunnel.end();

All 10 comments

It may be a while but I can try to enable this. Are you just using the TextBot class? I wouldn't expect your bot to work properly either. We designed everything with the assumption your bot would be running on some hosted service somewhere.

I'm using BotConnectorBot class. You can see here part of the code related to the LuisDialog connection:

// Create bot and add dialogs
var dialog = new builder.LuisDialog('https://api.projectoxford.ai...');
var bot = new builder.BotConnectorBot({ appId: 'MAPFRE_Delta', appSecret: 'YourAppSecret' });
var botSkype = new builder.SkypeBot(botService);
dialog.setThreshold(0.5);


dialog.on('BuscarInformacion', [

Do you think is it possible to find a way to make this work on this kind of network?

Thx!

if I try to use the global-tunnel package from npm and establish a proxy configuration, the error changes to the following one:

Error: Intent recognition error: Request path contains unescaped characters.

Hope that helps to find a way to solve this behavior.

thanks... not really :) So are you trying to host the bot locally on your own machines? If you look at the code for LuisDialog.recognize() you'll see that its like a few lines of code to make the REST call. You might try modifying this function to pass request your proxy info. If that works you can always just make your own copy of the LuisDialog class and use that but do please share the fix if you find one. Don't worry about the TypeScript files either, just modify the compiled JavaScript files.

Hi @Stevenic, I finally find a solution for this problem. Maybe this helps you if anyone or any company face the same problem.

We use the global-tunnel module to force the connections to go through the proxy. It uses the environment variable http_proxy and https_proxy, so you can easily use it, like you can see here:

var globalTunnel = require('global-tunnel');

process.env.http_proxy = 'http://proxy:80';
process.env.https_proxy = 'http://proxy:80';
globalTunnel.initialize();

Then you only have to initialize it before you instantiate the LuisDialog and you even can then close the proxy connection and be using your "normal" connection as you can see here:

var dialog = new builder.LuisDialog('https://api.projectoxford.ai/luis/v1/application?id=bb3b52f7-ba5a-4358-9b16-0a321fc4bc10&subscription-key=XXXX');
globalTunnel.end();

If you agree with me, maybe we can close the issue :)

Ok good. Thanks for working this out.

Hello alexandrev,
I tried your approach, but I am getting the below error:

Debugger listening on port 5858
restify listening to http://[::]:1337
Error: Intent recognition error: tunneling socket could not be established, cause=connect ETIMEDOUT 159.67.198.2:8080

Can u suggest here...

Regards,
Giri G.

Hi, below is a sample node.js app. Where exactly do we need to add the below proxy settings so that all traffic goes through the proxy. Reason we're doing that is that we're having a bot behind proxy and that we're getting a 407 error when the node.js app tries to access luis on http://api.projectoxford.ai:443

Code:
var globalTunnel = require('global-tunnel');
process.env.http_proxy = 'http://proxy:80';
process.env.https_proxy = 'http://proxy:80';
globalTunnel.initialize();
globalTunnel.end();

Node.js App:
var builder = require('botbuilder');

// Create bot and bind to console
var connector = new builder.ConsoleConnector().listen();
var bot = new builder.UniversalBot(connector);

// Create LUIS recognizer that points at our model and add it as the root '/' dialog for our Cortana Bot.
var model = 'https://api.projectoxford.ai/luis/v1/application?id=c413b2ef-382c-45bd-8ff0-f76d60e2a821&subscription-key=3e25eb6738844fdca4414b8c0a498cd0&q=';
var recognizer = new builder.LuisRecognizer(model);
var dialog = new builder.IntentDialog({ recognizers: [recognizer] });
bot.dialog('/', dialog);

// Add intent handlers
dialog.matches('builtin.intent.alarm.set_alarm', [
function (session, args, next) {
// Resolve and store any entities passed from LUIS.
var title = builder.EntityRecognizer.findEntity(args.entities, 'builtin.alarm.title');
var time = builder.EntityRecognizer.resolveTime(args.entities);
var alarm = session.dialogData.alarm = {
title: title ? title.entity : null,
timestamp: time ? time.getTime() : null

};

// Prompt for title
if (!alarm.title) {
    builder.Prompts.text(session, 'What would you like to call your alarm?');
} else {
    next();
}

},
function (session, results, next) {
var alarm = session.dialogData.alarm;
if (results.response) {
alarm.title = results.response;
}

// Prompt for time (title will be blank if the user said cancel)
if (alarm.title && !alarm.timestamp) {
    builder.Prompts.time(session, 'What time would you like to set the alarm for?');
} else {
    next();
}

},
function (session, results) {
var alarm = session.dialogData.alarm;
if (results.response) {
var time = builder.EntityRecognizer.resolveTime([results.response]);
alarm.timestamp = time ? time.getTime() : null;
}

// Set the alarm (if title or timestamp is blank the user said cancel)
if (alarm.title && alarm.timestamp) {
    // Save address of who to notify and write to scheduler.
    alarm.address = session.message.address;
    alarms[alarm.title] = alarm;

    // Send confirmation to user
    var date = new Date(alarm.timestamp);
    var isAM = date.getHours() < 12;
    session.send('Creating alarm named "%s" for %d/%d/%d %d:%02d%s',
        alarm.title,
        date.getMonth() + 1, date.getDate(), date.getFullYear(),
        isAM ? date.getHours() : date.getHours() - 12, date.getMinutes(), isAM ? 'am' : 'pm');
} else {
    session.send('Ok... no problem.');
}

}

]);

dialog.matches('builtin.intent.alarm.delete_alarm', [
function (session, args, next) {
// Resolve entities passed from LUIS.
var title;
var entity = builder.EntityRecognizer.findEntity(args.entities, 'builtin.alarm.title');
if (entity) {
// Verify its in our set of alarms.
title = builder.EntityRecognizer.findBestMatch(alarms, entity.entity);
}

// Prompt for alarm name
if (!title) {
    builder.Prompts.choice(session, 'Which alarm would you like to delete?', alarms);
} else {
    next({ response: title });
}

},
function (session, results) {
// If response is null the user canceled the task
if (results.response) {
delete alarms[results.response.entity];
session.send("Deleted the '%s' alarm.", results.response.entity);
} else {
session.send('Ok... no problem.');
}
}

]);

dialog.onDefault(builder.DialogAction.send("I'm sorry I didn't understand. I can only create & delete alarms."));

// Very simple alarm scheduler
var alarms = {};
setInterval(function () {
var now = new Date().getTime();
for (var key in alarms) {
var alarm = alarms[key];
if (now >= alarm.timestamp) {
var msg = new builder.Message()
.address(alarm.address)
.text("Here's your '%s' alarm.", alarm.title);
bot.send(msg);
delete alarms[key];
}
}
}, 15000);

Hi @alexandrev, what is the format to set the username and password details in process.env.http_proxy, process.env.https_proxy for the proxied network.

Was this page helpful?
0 / 5 - 0 ratings