From 6c436a481a478cde4a49b29983be852baf0ba49f Mon Sep 17 00:00:00 2001 From: Elad Iwanir <13205761+eladiw@users.noreply.github.com> Date: Mon, 6 Apr 2020 13:58:40 +0300 Subject: [PATCH 1/3] Supporting Windows and Linux web apps. Linux by default (#57) * Supporting Windows and Linux web apps. Linux by default * bug fix * update readme * adding doc * update readme --- README.md | 5 +- azuredeploy.json | 128 ++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 120 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 30caa9f..0332eaf 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,9 @@ A simple web page to hand off users to the Microsoft Health bot [![Deploy to Azure](https://azuredeploy.net/deploybutton.png)](https://azuredeploy.net/) +Note: It is recommended you use the default Linux host type when deploying the container. +However, if you wish to enable online file editing using the App Service Editor, select 'Windows'. + 2.Set the following environment variables: `APP_SECRET` @@ -48,7 +51,7 @@ In some cases it is required to set the endpoint URI so that it points to a spec Pass your preferred geographic endpoint URI by setting the environment variable: `DIRECTLINE_ENDPOINT_URI` in your deployment. If no variable is found it will default to `directline.botframework.com` -**Note:** If you are deploying the code sample using the "Deploy to Azure" option, you should add the above secrets to the application settings for your App Service. +**Note:** If you are deploying the code sample using the "Deploy to Azure" option, you should add the above secrets to the application settings for your App Service. ## Agent webchat If the agent webchat sample is also required, [switch to the live agent handoff branch](https://github.com/Microsoft/HealthBotContainerSample/tree/live_agent_handoff) diff --git a/azuredeploy.json b/azuredeploy.json index 7e5f0ed..f7b8d45 100644 --- a/azuredeploy.json +++ b/azuredeploy.json @@ -7,13 +7,24 @@ "defaultValue": "[concat('HealthBot', uniqueString(resourceGroup().name, utcNow('F')))]", "metadata":{ "description": "Web site name. Has to be unique." - + + } + }, + "serverKind": { + "type": "string", + "defaultValue": "linux", + "allowedValues": [ + "linux", + "windows" + ], + "metadata": { + "description": "Host type: Linux or Windows. (Linux is recommended)" } }, "skuName": { "type": "string", "defaultValue": "P1V2", - "allowedValues": [ + "allowedValues": [ "B1", "S1", "P1V2" @@ -44,7 +55,7 @@ "webchatSecret": { "type": "securestring", "metadata":{ - "description": "Healthbot webchat secret." + "description": "Healthbot webchat secret." } } }, @@ -53,21 +64,33 @@ "skuCode": "[parameters('skuName')]", "numberOfWorkers": "[parameters('numberOfInstances')]", "linuxFxVersion": "NODE|lts", - "hostingPlanName": "[concat('hpn-', parameters('siteName'))]", + "hostingPlanNameLinux": "[concat('hpn-', parameters('siteName'))]", + "hostingPlanNameWin": "[concat('hpn-win-', parameters('siteName'))]", "repoURL": "https://github.com/microsoft/HealthBotContainerSample.git", - "branch": "master" + "branch": "master", + "kind": "[if(equals(parameters('serverKind'), 'windows'), 'app', 'linux')]", + "linuxSiteName": "[concat(parameters('siteName'), 'linux')]", + "windowsSiteName": "[concat(parameters('siteName'), 'windows')]", + "WinSkuCode": "[parameters('skuName')]", + "WinSku": "Standard", + "workerSize": "0", + "workerSizeId": "0", + "hostingEnvironment": "", + "nodeVersion": "12.13.0", + "currentStack": "node" }, "resources": [ { "apiVersion": "2018-02-01", - "name": "[parameters('siteName')]", + "name": "[variables('linuxSiteName')]", + "condition": "[equals(parameters('serverKind'),'linux')]", "type": "Microsoft.Web/sites", "location": "[parameters('siteLocation')]", "dependsOn": [ - "[resourceId('Microsoft.Web/serverfarms/', variables('hostingPlanName'))]" + "[resourceId('Microsoft.Web/serverfarms/', variables('hostingPlanNameLinux'))]" ], "properties": { - "name": "[parameters('siteName')]", + "name": "[variables('linuxSiteName')]", "siteConfig": { "linuxFxVersion": "[variables('linuxFxVersion')]", "alwaysOn": "[variables('alwaysOn')]", @@ -82,17 +105,18 @@ } ] }, - "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]", + "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanNameLinux'))]", "clientAffinityEnabled": false }, "resources": [ { "type": "sourcecontrols", + "condition": "[equals(parameters('serverKind'),'linux')]", "apiVersion": "2018-02-01", "name": "web", "location": "[parameters('siteLocation')]", "dependsOn": [ - "[resourceId('Microsoft.Web/sites', parameters('siteName'))]" + "[resourceId('Microsoft.Web/sites', variables('linuxSiteName'))]" ], "properties": { "repoUrl": "[variables('repoURL')]", @@ -104,7 +128,8 @@ }, { "apiVersion": "2018-02-01", - "name": "[variables('hostingPlanName')]", + "condition": "[equals(parameters('serverKind'),'linux')]", + "name": "[variables('hostingPlanNameLinux')]", "type": "Microsoft.Web/serverfarms", "location": "[parameters('siteLocation')]", "kind": "linux", @@ -112,10 +137,89 @@ "Name": "[variables('skuCode')]" }, "properties": { - "name": "[variables('hostingPlanName')]", + "name": "[variables('hostingPlanNameLinux')]", "numberOfWorkers": "[variables('numberOfWorkers')]", "reserved": true } + }, + { + "apiVersion": "2018-11-01", + "condition": "[equals(parameters('serverKind'),'windows')]", + "name": "[variables('windowsSiteName')]", + "type": "Microsoft.Web/sites", + "location": "[parameters('siteLocation')]", + "tags": null, + "dependsOn": [ + "[concat('Microsoft.Web/serverfarms/', variables('hostingPlanNameWin'))]" + ], + "properties": { + "name": "[variables('windowsSiteName')]", + "siteConfig": { + "appSettings": [ + { + "name": "APP_SECRET", + "value": "[parameters('appSecret')]" + }, + { + "name": "WEBCHAT_SECRET", + "value": "[parameters('webchatSecret')]" + }, + { + "name": "WEBSITE_NODE_DEFAULT_VERSION", + "value": "[variables('nodeVersion')]" + } + ], + "metadata": [ + { + "name": "CURRENT_STACK", + "value": "[variables('currentStack')]" + } + ], + "nodeVersion": "[variables('nodeVersion')]", + "alwaysOn": "[variables('alwaysOn')]" + }, + "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanNameWin'))]", + "hostingEnvironment": "[variables('hostingEnvironment')]", + "clientAffinityEnabled": true + }, + "resources": [ + { + "type": "sourcecontrols", + "condition": "[equals(parameters('serverKind'),'windows')]", + "apiVersion": "2018-11-01", + "name": "web", + "location": "[parameters('siteLocation')]", + "dependsOn": [ + "[resourceId('Microsoft.Web/sites', variables('windowsSiteName'))]" + ], + "properties": { + "repoUrl": "[variables('repoURL')]", + "branch": "[variables('branch')]", + "isManualIntegration": true + } + } + ] + }, + { + "apiVersion": "2018-11-01", + "name": "[variables('hostingPlanNameWin')]", + "condition": "[equals(parameters('serverKind'),'windows')]", + "type": "Microsoft.Web/serverfarms", + "location": "[parameters('siteLocation')]", + "kind": "", + "tags": null, + "dependsOn": [], + "properties": { + "name": "[variables('hostingPlanNameWin')]", + "workerSize": "[variables('workerSize')]", + "workerSizeId": "[variables('workerSizeId')]", + "numberOfWorkers": "[variables('numberOfWorkers')]", + "hostingEnvironment": "[variables('hostingEnvironment')]" + }, + "sku": { + "Tier": "[variables('WinSku')]", + "Name": "[variables('WinSkuCode')]" + } } ] } \ No newline at end of file From c134e60d0b0fa33a4788c36e2e257fcdff260717 Mon Sep 17 00:00:00 2001 From: GuyBeckerMicrosoft <61974899+GuyBeckerMicrosoft@users.noreply.github.com> Date: Tue, 7 Apr 2020 19:26:01 +0300 Subject: [PATCH 2/3] Origin/deployment script update (#64) --- azuredeploy.json | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/azuredeploy.json b/azuredeploy.json index f7b8d45..38f1973 100644 --- a/azuredeploy.json +++ b/azuredeploy.json @@ -10,7 +10,7 @@ } }, - "serverKind": { + "operatingSystem": { "type": "string", "defaultValue": "linux", "allowedValues": [ @@ -64,13 +64,13 @@ "skuCode": "[parameters('skuName')]", "numberOfWorkers": "[parameters('numberOfInstances')]", "linuxFxVersion": "NODE|lts", - "hostingPlanNameLinux": "[concat('hpn-', parameters('siteName'))]", - "hostingPlanNameWin": "[concat('hpn-win-', parameters('siteName'))]", + "hostingPlanNameLinux": "[concat('plan-linux-', parameters('siteName'))]", + "hostingPlanNameWin": "[concat('plan-win-', parameters('siteName'))]", "repoURL": "https://github.com/microsoft/HealthBotContainerSample.git", "branch": "master", - "kind": "[if(equals(parameters('serverKind'), 'windows'), 'app', 'linux')]", - "linuxSiteName": "[concat(parameters('siteName'), 'linux')]", - "windowsSiteName": "[concat(parameters('siteName'), 'windows')]", + "kind": "[if(equals(parameters('operatingSystem'), 'windows'), 'app', 'linux')]", + "linuxSiteName": "[if(equals(parameters('operatingSystem'), 'linux'), parameters('siteName'), 'app-na')]", + "windowsSiteName": "[if(equals(parameters('operatingSystem'), 'windows'), parameters('siteName'), 'app-na')]", "WinSkuCode": "[parameters('skuName')]", "WinSku": "Standard", "workerSize": "0", @@ -83,7 +83,7 @@ { "apiVersion": "2018-02-01", "name": "[variables('linuxSiteName')]", - "condition": "[equals(parameters('serverKind'),'linux')]", + "condition": "[equals(parameters('operatingSystem'),'linux')]", "type": "Microsoft.Web/sites", "location": "[parameters('siteLocation')]", "dependsOn": [ @@ -111,7 +111,7 @@ "resources": [ { "type": "sourcecontrols", - "condition": "[equals(parameters('serverKind'),'linux')]", + "condition": "[equals(parameters('operatingSystem'),'linux')]", "apiVersion": "2018-02-01", "name": "web", "location": "[parameters('siteLocation')]", @@ -128,7 +128,7 @@ }, { "apiVersion": "2018-02-01", - "condition": "[equals(parameters('serverKind'),'linux')]", + "condition": "[equals(parameters('operatingSystem'),'linux')]", "name": "[variables('hostingPlanNameLinux')]", "type": "Microsoft.Web/serverfarms", "location": "[parameters('siteLocation')]", @@ -144,7 +144,7 @@ }, { "apiVersion": "2018-11-01", - "condition": "[equals(parameters('serverKind'),'windows')]", + "condition": "[equals(parameters('operatingSystem'),'windows')]", "name": "[variables('windowsSiteName')]", "type": "Microsoft.Web/sites", "location": "[parameters('siteLocation')]", @@ -185,7 +185,7 @@ "resources": [ { "type": "sourcecontrols", - "condition": "[equals(parameters('serverKind'),'windows')]", + "condition": "[equals(parameters('operatingSystem'),'windows')]", "apiVersion": "2018-11-01", "name": "web", "location": "[parameters('siteLocation')]", @@ -203,7 +203,7 @@ { "apiVersion": "2018-11-01", "name": "[variables('hostingPlanNameWin')]", - "condition": "[equals(parameters('serverKind'),'windows')]", + "condition": "[equals(parameters('operatingSystem'),'windows')]", "type": "Microsoft.Web/serverfarms", "location": "[parameters('siteLocation')]", "kind": "", From f97e69e462da4041b67b09cb30a0e4793fbe4614 Mon Sep 17 00:00:00 2001 From: amir-microsoft <44203837+amir-microsoft@users.noreply.github.com> Date: Tue, 7 Apr 2020 20:01:05 +0300 Subject: [PATCH 3/3] Removing locale validation: (#63) Current locale validation doesn't support all cases, such as: de, zh-Hant-TW, En-au,aZ_cYrl-aZ The locale is validated in the WebChat app anyway so it's redundant. --- public/index.js | 14 ++++++-------- server.js | 11 +---------- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/public/index.js b/public/index.js index 3c4b3cb..d44cb55 100644 --- a/public/index.js +++ b/public/index.js @@ -1,12 +1,10 @@ const defaultLocale = 'en-US'; -const localeRegExPattern = /^[a-z]{2}(-[A-Z]{2})?$/; function requestChatBot(loc) { const params = new URLSearchParams(location.search); - const locale = params.has('locale') ? extractLocale(params.get('locale')) : defaultLocale; const oReq = new XMLHttpRequest(); oReq.addEventListener("load", initBotConversation); - var path = "/chatBot?locale=" + locale; + var path = "/chatBot?locale=" + extractLocale(params.get('locale')); if (loc) { path += "&lat=" + loc.lat + "&long=" + loc.long; @@ -22,15 +20,15 @@ function requestChatBot(loc) { } function extractLocale(localeParam) { - if(localeParam === 'autodetect') { + if (!localeParam) { + return defaultLocale; + } + else if (localeParam === 'autodetect') { return navigator.language; } - - //Before assigning, ensure it's a valid locale string (xx or xx-XX) - if(localeParam.search(localeRegExPattern) === 0) { + else { return localeParam; } - return defaultLocale; } function chatRequested() { diff --git a/server.js b/server.js index d37695b..412cc5a 100644 --- a/server.js +++ b/server.js @@ -1,6 +1,4 @@ require('dotenv').config(); -const defaultLocale = 'en-US'; -const localeRegExPattern = /^[a-z]{2}(-[A-Z]{2})?$/; const crypto = require('crypto'); const express = require("express"); const path = require("path"); @@ -31,13 +29,6 @@ function isUserAuthenticated(){ return true; } -function getValidatedLocale(loc) { - if (loc.search(localeRegExPattern) === 0) { - return loc; - } - return defaultLocale; -} - const appConfig = { isHealthy : false, options : { @@ -96,7 +87,7 @@ app.post('/chatBot', function(req, res) { var response = {}; response['userId'] = userid; response['userName'] = req.query.userName; - response['locale'] = getValidatedLocale(req.query.locale); + response['locale'] = req.query.locale; response['connectorToken'] = parsedBody.token; /*