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

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions