首页 > 解决方案 > 无法在 Bot Framework Emulator 中建立隧道套接字

问题描述

我发现在将 botbuilder 软件包升级到高于 4.7 的版本后,我不再能够在本地使用 Bot Framework Emulator(不使用 ngrok,我的公司不允许)(编辑:我现在已经检查过了,错误似乎是中引入4.10。它在版本上运行良好,4.9只保留botbuilder-testing包在4.9没有帮助)。谁能告诉我发生了什么变化导致这不起作用,以及是否有办法继续在本地进行测试?这在我使用的任何时候都会失败await context.sendActivity(我确信其他东西也不能正常工作,但这是我能得到的)。这是我设置机器人适配器的方法。AppId 和 Password 为NULL,因为我在本地运行它而不使用 ngrok。

const adapter = new BotFrameworkAdapter({
    appId: process.env.MicrosoftAppId, // this variable is null for local/emulator
    appPassword: process.env.MicrosoftAppPassword // this variable is null for local/emulator
});

这是完整的错误信息。是的,我知道我没有发现错误,但我不会为每个 sendActivity 语句放置一个 try catch 块。错误细节没有什么不同。

(node:19488) UnhandledPromiseRejectionWarning: Error: BotFrameworkAdapter.processActivity(): 500 ERROR
 Error: tunneling socket could not be established, statusCode=403
    at new RestError (C:\Users\e0077301\Documents\DevOps Projects\TRaCy nanorep\node_modules\@azure\ms-rest-js\dist\msRest.node.js:1403:28)
    at AxiosHttpClient.<anonymous> (C:\Users\e0077301\Documents\DevOps Projects\TRaCy nanorep\node_modules\@azure\ms-rest-js\dist\msRest.node.js:2194:35)
    at step (C:\Users\e0077301\Documents\DevOps Projects\TRaCy nanorep\node_modules\tslib\tslib.js:133:27)
    at Object.throw (C:\Users\e0077301\Documents\DevOps Projects\TRaCy nanorep\node_modules\tslib\tslib.js:114:57)
    at rejected (C:\Users\e0077301\Documents\DevOps Projects\TRaCy nanorep\node_modules\tslib\tslib.js:105:69)
    at process._tickCallback (internal/process/next_tick.js:68:7)
    at BotFrameworkAdapter.<anonymous> (C:\Users\e0077301\Documents\DevOps Projects\TRaCy nanorep\node_modules\botbuilder\lib\botFrameworkAdapter.js:736:27)
    at Generator.throw (<anonymous>)
    at rejected (C:\Users\e0077301\Documents\DevOps Projects\TRaCy nanorep\node_modules\botbuilder\lib\botFrameworkAdapter.js:13:65)
    at process._tickCallback (internal/process/next_tick.js:68:7)

以下是完整的 index.js 和 package.json 文件:

index.js

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

const path = require('path');
const ENV_FILE = path.join(__dirname, '.env');
require('dotenv').config({ path: ENV_FILE });
const request = require('request-promise-native');

// Import and start application insights
const appInsights = require('applicationinsights');
appInsights.setup(process.env.APPINSIGHTS_INSTRUMENTATIONKEY).start();
const appInsightsClient = appInsights.defaultClient;

// Import required packages
const restify = require('restify');
const { CustomLogger } = require('./helpers/CustomLogger');

// Import required bot services. See https://aka.ms/bot-services to learn more about the different parts of a bot.
const { BotFrameworkAdapter, MemoryStorage, ConversationState, UserState, TranscriptLoggerMiddleware } = require('botbuilder');
const { BlobStorage } = require('botbuilder-azure');

// This bot's main dialog.
const { DispatchBot } = require('./bots/dispatchBot');

// Create adapter.
// See https://aka.ms/about-bot-adapter to learn more about adapters.
const adapter = new BotFrameworkAdapter({
    appId: process.env.MicrosoftAppId,
    appPassword: process.env.MicrosoftAppPassword
});

// Catch-all for errors.
adapter.onTurnError = async (context, error) => {

    console.error(`\n [onTurnError]: ${ error }`);
    
    // Log to Application Insights
    appInsightsClient.trackTrace({
        message: `${error.name} - ${path.basename(__filename)}`,
        severity: 4,
        properties: {'error':error.message,'callStack':error.stack,'botName': process.env.BOTNAME}
    });

    // Send a message to the user
    await context.sendActivity(`Sorry, I've encountered an unexpected error and I had to cancel our last activity. If you continue to receive this error, please contact your support team.`);
    
    // Clear out state
    await conversationState.delete(context);
};



if (process.env.BOTNAME == 'Bot_Local') {
    // Memory storage - for development only
    console.log(`\nUsing MemoryStorage for state storage`);
    const memoryStorage = new MemoryStorage();
    var conversationState = new ConversationState(memoryStorage);
    var userState = new UserState(memoryStorage);
} else {
    // Blob storage - for production
    console.log(`\nUsing BlobStorage for state storage`);
    const blobStorage = new BlobStorage({
        containerName: 'bot-storage',
        storageAccountOrConnectionString: process.env.blobStorageServiceName,
        storageAccessKey: process.env.blobStorageAccessKey
    });
    var conversationState = new ConversationState(blobStorage);
    var userState = new UserState(blobStorage);
}

// Set up transcript logger
const transcriptLogger = new TranscriptLoggerMiddleware(new CustomLogger(appInsightsClient));
adapter.use(transcriptLogger);

// Pass in a logger to the bot.
//const logger = console;
const logger = appInsightsClient;

// Create the main dialog
let bot = new DispatchBot(conversationState, userState, logger);

// Create HTTP server
let server = restify.createServer();
server.listen(process.env.port || process.env.PORT || 3978, function() {
    console.log(`\n${ server.name } listening to ${ server.url }`);
    console.log(`\nGet Bot Framework Emulator: https://aka.ms/botframework-emulator`);
    console.log(`\nSee https://aka.ms/connect-to-bot for more information`);
});
const restifyBodyParser = require('restify').plugins.bodyParser;
server.use(restifyBodyParser());

// Listen for incoming activities and route them to your bot main dialog.
server.post('/api/messages', (req, res) => {
    // Route received a request to adapter for processing
    adapter.processActivity(req, res, async (turnContext) => {
        // route to bot activity handler.
        await bot.run(turnContext);
    });
});

// Respond to pings
server.get('/api/ping', (req, res) => {
    res.send('Ping acknowledged');
});

// Listen for incoming notifications and send proactive messages to users.
server.post('/api/notify', async (req, res) => {
    console.log(req.body);

    try {
        const conversationReference = req.body.conversationReference;
        await adapter.continueConversation(conversationReference, async turnContext => {
            // If you encounter permission-related errors when sending this message, see
            // https://aka.ms/BotTrustServiceUrl
            await turnContext.sendActivity(req.body.message);
        });

        res.setHeader('Content-Type', 'text/html');
        res.writeHead(200);
        res.write('<html><body><h1>Proactive messages have been sent.</h1></body></html>');
        res.end();
    } catch (error) {
        console.log('Bad request');
        appInsightsClient.trackTrace({
            message: `${error.name} - ${path.basename(__filename)} /api/notify`,
            severity: 4,
            properties: {'error':error.message,'callStack':error.stack,'botName': process.env.BOTNAME}
        });

        res.setHeader('Content-Type', 'text/html');
        res.writeHead(400);
        res.write('<html><body><h1>Bad Request. Please ensure your message contains the conversation reference and message text.</h1></body></html>');
        res.end();
    }
});

server.post('/directline/token', async (req, res) => {

    try {
        var body = {User:{Id:req.body.userId}};
        const response = await request({
            url: 'https://directline.botframework.com/v3/directline/tokens/generate',
            method: 'POST',
            headers: { Authorization: `Bearer ${process.env.DIRECTLINE_SECRET}`},
            json: body,
            rejectUnauthorized: false
        });
        const token = response.token;
        res.setHeader('Content-Type', 'text/plain');
        res.writeHead(200);
        res.write(token);
        res.end();
    } catch(err) {
        console.log(err);
        res.setHeader('Content-Type', 'text/plain');
        res.writeHead(500);
        res.write('Call to retrieve token from Direct Line failed');
        res.end();
    }
})

package.json (将 botbuilder 包更新到最新版本。如果我将它们全部降级到 4.7.0 就可以了)

{
  "name": "core-bot",
  "version": "1.0.0",
  "description": "A bot that demonstrates core AI capabilities",
  "author": "Microsoft",
  "license": "MIT",
  "main": "index.js",
  "nyc": {
    "exclude": [
      "test",
      "helpers/cardHelper.js"
    ]
  },
  "scripts": {
    "start": "node ./index.js",
    "watch": "nodemon ./index.js",
    "lint": "eslint .",
    "test:dev": "mocha test/**/*test.js",
    "test": "nyc --reporter=text --reporter=cobertura  mocha test/**/*test.js --timeout 10000 --reporter mocha-multi-reporters --reporter-options configFile=./mocha-reporter-config.json",
    "test:inspect": "mocha test/**/*test.js --inspect-brk",
    "testList": "node ./node_modules/mocha-list-tests/mocha-list-tests.js test/"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/Microsoft/BotBuilder-Samples.git"
  },
  "dependencies": {
    "@microsoft/recognizers-text-data-types-timex-expression": "^1.1.4",
    "@sendgrid/mail": "^6.4.0",
    "applicationinsights": "^1.6.0",
    "azure-storage": "^2.10.3",
    "botbuilder": "^4.12.0",
    "botbuilder-ai": "^4.12.0",
    "botbuilder-azure": "^4.12.0",
    "botbuilder-dialogs": "^4.12.0",
    "botbuilder-testing": "^4.12.0",
    "crypto": "^1.0.1",
    "dotenv": "^6.1.0",
    "mocha": "^6.2.2",
    "mocha-list-tests": "^1.0.2",
    "nock": "^11.7.0",
    "remove-markdown": "^0.3.0",
    "restify": "^7.2.3",
    "turndown": "^5.0.3",
    "xml2js": "^0.4.22"
  },
  "devDependencies": {
    "eslint": "^5.16.0",
    "eslint-config-standard": "^12.0.0",
    "eslint-plugin-import": "^2.19.1",
    "eslint-plugin-node": "^8.0.0",
    "eslint-plugin-promise": "^4.2.1",
    "eslint-plugin-standard": "^4.0.1",
    "https-proxy-agent": "^5.0.0",
    "mocha-junit-reporter": "^1.23.1",
    "mocha-multi-reporters": "^1.1.7",
    "nodemon": "^1.19.4",
    "nyc": "^14.1.1",
    "source-map-support": "^0.5.16"
  }
}

标签: botframework

解决方案


如果您在 Windows 机器上,请尝试设置此系统环境变量 -NODE_TLS_REJECT_UNAUTHORIZED=0而不是HTTPS_PROXY. 这解决了在 http 协议上运行的模拟器 localhost 问题,以开始与 https 上的服务进行通信。代理设置不再适用于 botbuilder 包 4.10 及更高版本。


推荐阅读