Bug Description
Two related bugs in SDK v2.0.6+ that affect HTTPS support and Azure App Service deployments.
Bug 1: ExpressAdapter constructor doesn't recognize https.Server
Root cause: The ExpressAdapter constructor uses instanceof http.Server to detect if a server was passed:
// packages/apps/src/http/express-adapter.ts
if (serverOrApp instanceof http.Server) {
this.express = express();
this.server = serverOrApp;
this.server.on('request', this.express);
} else if (typeof serverOrApp === 'function') {
this.express = serverOrApp;
} else {
this.express = express();
this.server = http.createServer(this.express);
}
https.createServer() returns an https.Server which inherits from tls.Server → net.Server — it is not instanceof http.Server. So the check fails silently, and the adapter falls into the else branch, creating a new plain HTTP server and discarding the HTTPS server.
Impact: When using new HttpPlugin(https.createServer(sslOptions)) or new ExpressAdapter(httpsServer), the HTTPS server is silently ignored. Only http:// works; https:// fails.
Worked in v2.0.5 because the old HttpPlugin used the server directly without this instanceof check.
Suggested fix: Use instanceof net.Server or duck-typing (e.g., check for .listen method) instead of instanceof http.Server.
Bug 2: DevtoolsPlugin crashes on Azure App Service named pipe ports
Root cause: On Azure App Service (Windows, IIS + iisnode), process.env.PORT is a Windows named pipe (e.g., \\.\pipe\507cb72a-...). The DevtoolsPlugin.onStart() does:
// packages/dev/src/plugin.ts
const numericPort = this.options.customPort ?? (typeof port === 'string' ? parseInt(port, 10) + 1 : port + 1);
// ...
this.http.listen(numericPort); // numericPort = NaN
parseInt('\\.\pipe\507cb72a-...', 10) returns NaN, so NaN + 1 = NaN, and this.http.listen(NaN) crashes the entire app.
Impact: The app returns 500/503 on Azure App Service. The DevtoolsPlugin warning says "should not be used in production environments" but it still crashes the app rather than gracefully skipping.
Suggested fix: Guard against non-numeric ports — if parseInt returns NaN, either skip starting the devtools server or log a warning and continue.
Steps to Reproduce
Bug 1:
- Create a tab app with
@microsoft/teams.apps@2.0.7
- Configure SSL certificates and use
new HttpPlugin(https.createServer(sslOptions))
- Try to access
https://localhost:3978/tabs/home/
- Result: Connection fails. Only
http:// works.
Bug 2:
- Create any app with
DevtoolsPlugin in the plugins array
- Deploy to Azure App Service (Windows, IIS + iisnode)
- Result: App crashes with 500/503
Expected Behavior
ExpressAdapter should accept https.Server the same way it accepts http.Server
DevtoolsPlugin should gracefully handle non-numeric ports
SDK Version
2.0.7
Node.js Version
22.22.0
Workaround
// Bug 1: Patch the adapter's internal server after construction
const adapter = new ExpressAdapter();
if (sslOptions.cert && sslOptions.key) {
const httpsServer = https.createServer(sslOptions, (adapter as any).express);
(adapter as any).server = httpsServer;
}
// Bug 2: Only load DevtoolsPlugin in local dev
const plugins: IPlugin[] = [];
if (process.env.SSL_KEY_FILE) {
plugins.push(new DevtoolsPlugin());
}
// Don't coerce PORT to number — pass as-is for named pipe support
await app.start(process.env.PORT || 3978);
Related PRs
Bug Description
Two related bugs in SDK v2.0.6+ that affect HTTPS support and Azure App Service deployments.
Bug 1:
ExpressAdapterconstructor doesn't recognizehttps.ServerRoot cause: The
ExpressAdapterconstructor usesinstanceof http.Serverto detect if a server was passed:https.createServer()returns anhttps.Serverwhich inherits fromtls.Server → net.Server— it is notinstanceof http.Server. So the check fails silently, and the adapter falls into theelsebranch, creating a new plain HTTP server and discarding the HTTPS server.Impact: When using
new HttpPlugin(https.createServer(sslOptions))ornew ExpressAdapter(httpsServer), the HTTPS server is silently ignored. Onlyhttp://works;https://fails.Worked in v2.0.5 because the old
HttpPluginused the server directly without thisinstanceofcheck.Suggested fix: Use
instanceof net.Serveror duck-typing (e.g., check for.listenmethod) instead ofinstanceof http.Server.Bug 2:
DevtoolsPlugincrashes on Azure App Service named pipe portsRoot cause: On Azure App Service (Windows, IIS + iisnode),
process.env.PORTis a Windows named pipe (e.g.,\\.\pipe\507cb72a-...). TheDevtoolsPlugin.onStart()does:parseInt('\\.\pipe\507cb72a-...', 10)returnsNaN, soNaN + 1 = NaN, andthis.http.listen(NaN)crashes the entire app.Impact: The app returns 500/503 on Azure App Service. The DevtoolsPlugin warning says "should not be used in production environments" but it still crashes the app rather than gracefully skipping.
Suggested fix: Guard against non-numeric ports — if
parseIntreturnsNaN, either skip starting the devtools server or log a warning and continue.Steps to Reproduce
Bug 1:
@microsoft/teams.apps@2.0.7new HttpPlugin(https.createServer(sslOptions))https://localhost:3978/tabs/home/http://works.Bug 2:
DevtoolsPluginin the plugins arrayExpected Behavior
ExpressAdaptershould accepthttps.Serverthe same way it acceptshttp.ServerDevtoolsPluginshould gracefully handle non-numeric portsSDK Version
2.0.7
Node.js Version
22.22.0
Workaround
Related PRs
ExpressAdapter)parseIntinHttpServer.start(), but not inDevtoolsPlugin)