HttpPlatformHandler returns a random port because it reads the port from the
PORT environment variable, which IIS Express assigns dynamically. To fix this, you must explicitly set the
PORT variable to 3000 in your
web.config file. This overrides the default behavior and forces Node.js to listen on the expected address.
Understanding the HttpPlatformHandler Configuration
The HttpPlatformHandler is an IIS module that allows you to run non-.NET applications, such as Node.js, behind IIS. When you deploy a Node.js application to Azure Web Apps or configure it locally with IIS Express, the handler acts as a reverse proxy. It forwards incoming HTTP requests from the public-facing URL to your local Node.js process.
A common point of confusion arises when developers hardcode the port in their Node.js startup script but still experience connection failures. The issue is not with the code itself, but with how the environment is configured. IIS does not know which port your application is listening on unless you tell it. If you do not specify a port, the platform assigns a random available port for security and isolation reasons. Your Node.js app might be stuck listening on port 3000, while IIS is trying to connect to port 8421, resulting in a broken pipe or connection refused error.
To resolve this, you need to align the port expectation of the handler with the actual port your application uses. This involves editing the
web.config file located in the root directory of your web application. This XML file controls how IIS processes requests for your site.
Modifying web.config to Set the Port
The most reliable way to fix the random port issue is to add an environment variable entry in the
web.config file. This ensures that every time the Node.js process starts, it receives the correct port number via the standard
process.env.PORT mechanism.
Open your
web.config file in a text editor. You will see sections defining the handlers and modules. Locate the
<system.webServer> section. Inside this section, you need to add an
<environmentVariables> block.
Here is the structure you should use:
<system.webServer>
<handlers>
<add name="httpPlatformHandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" />
</handlers>
<httpPlatform processPath="node" arguments=".\server.js" stdoutLogEnabled="true" stdoutLogFile=".\\logs\\stdout" port="3000" />
</system.webServer>
Notice the
port="3000" attribute inside the
<httpPlatform> element. This tells the handler that the backend process (Node.js) is listening on port 3000. However, simply setting this attribute is often not enough for all platforms, especially if the application relies heavily on the
PORT environment variable for dynamic routing. Therefore, it is best practice to also define the environment variable explicitly.
Add the following block inside
<system.webServer>:
<environmentVariables>
<environmentVariable name="PORT" value="3000" />
</environmentVariables>
This combination ensures that both the IIS module knows where to send traffic and the Node.js process knows which port to bind to. After making these changes, save the file and restart your IIS Express instance or publish the application again.
Verifying the Node.js Startup Code
Once the configuration is updated, you must ensure your Node.js code actually respects the
PORT environment variable. Many starter templates hardcode the port like this:
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
While this works locally, it will fail in production environments managed by HttpPlatformHandler because the hardcoded value ignores the environment variable. You should modify your startup logic to check for the environment variable first, falling back to 3000 only if it is undefined.
Update your server initialization code to look like this:
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
This pattern is robust and works across development, testing, and production environments. It allows IIS to control the port via configuration while maintaining a sensible default for local development. If you are using frameworks like Express, Hapi, or Koa, this approach remains valid as they all support binding to a specific port passed as an argument.
Troubleshooting Common Issues
If you have applied the fixes above and still face issues, consider the following diagnostic steps. First, check the stdout log file specified in your
web.config. This file captures the console output from your Node.js process. Look for any errors indicating that port 3000 is already in use. If another process is occupying the port, change the value in
web.config to an unused port, such as 3001, and update your Node.js code accordingly.
Second, verify that IIS Express is actually reloading the configuration. Sometimes, cached configurations can persist even after you edit
web.config. Restarting the application pool or stopping and starting IIS Express usually clears this state.
Third, ensure that your firewall settings are not blocking localhost connections on port 3000. While rare in local development, some security software may interfere with loopback addresses.
For related issues regarding Node.js permissions, you might find
Access Denied Error: Node.js Works, but npm Commands Fail helpful if you encounter permission-related errors during deployment.
Frequently Asked Questions
Why does IIS assign a random port instead of using my code's port?
IIS assigns a random port to prevent conflicts between multiple applications running on the same server. Without explicit configuration, the HttpPlatformHandler cannot guess which port your specific Node.js instance is listening on. You must explicitly define the port in
web.config to bridge this gap.
Can I use a different port than 3000?
Yes, you can use any available TCP port. Simply change the
port attribute in
<httpPlatform> and the
value in
<environmentVariable> to your desired number. Ensure your Node.js code uses the
process.env.PORT variable to remain flexible.
What if I get a "Port Already in Use" error?
This error means another process is already bound to port 3000. Check your task manager for other Node instances or services. Change the port number in your
web.config to something else, like 3001, and update your environment variable accordingly.
Does this fix work for Azure App Service?
Yes, Azure App Service uses HttpPlatformHandler under the hood for Linux containers and certain Windows scenarios. The same
web.config modifications apply. Azure also injects the
PORT environment variable automatically, so ensuring your code reads it is crucial.
How do I enable logging to debug port issues?
Set
stdoutLogEnabled="true" and specify a
stdoutLogFile path in your
httpPlatform handler definition. This creates a log file that records the output of your Node.js process, allowing you to see exactly which port the server claims to be listening on at startup.