Skip to content

[Bug]: ExpressAdapter fails with HTTPS servers; DevtoolsPlugin crashes on Azure App Service named pipe ports #511

@Alive-Fish

Description

@Alive-Fish

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:

  1. Create a tab app with @microsoft/teams.apps@2.0.7
  2. Configure SSL certificates and use new HttpPlugin(https.createServer(sslOptions))
  3. Try to access https://localhost:3978/tabs/home/
  4. Result: Connection fails. Only http:// works.

Bug 2:

  1. Create any app with DevtoolsPlugin in the plugins array
  2. Deploy to Azure App Service (Windows, IIS + iisnode)
  3. Result: App crashes with 500/503

Expected Behavior

  1. ExpressAdapter should accept https.Server the same way it accepts http.Server
  2. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions