I have a Node Application I'd like to run using IIS. The problem is my configuration file. I am using IIS 10.0 and don't know how to configure everything correctly? Whenever I include both of these rules in my Web.Config file...
<!-- First we consider whether the incoming URL matches a physical file in the /public folder -->
<rule name="StaticContent" patternSyntax="Wildcard">
<action type="Rewrite" url="public/{R:0}" logRewrittenUrl="true"/>
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
</conditions>
<match url="*.*"/>
</rule>
<!-- All other URLs are mapped to the Node.js application entry point -->
<rule name="DynamicContent">
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
</conditions>
<action type="Rewrite" url="server.js"/>
</rule>
...I get a 500.1000 Error that looks like this:
When I take one or the other out, my websites pages and links load correctly but ALL POST requests create a 404 error? Because it's searching for a physical path instead of calling a POST function in my server.js file?
Here is the 404 ERROR:
I know that my site works, because it works (GET & POST requests) in the debugger for VS 2015. Here are snippets from my code and the configuration file.
Here is the full Web.Config file :
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<!--
All appSettings are made available to your Node.js app via environment variables
You can access them in your app through the process.env object.
process.env.<key>
-->
<!-- Unconmment the below appSetting if you'd like to use a Virtual Directory -->
<!-- <add key="virtualDirPath" value="" /> -->
</appSettings>
<system.webServer>
<iisnode node_env="%node_env%"
nodeProcessCountPerApplication="1"
maxConcurrentRequestsPerProcess="1024"
maxNamedPipeConnectionRetry="100"
namedPipeConnectionRetryDelay="250"
maxNamedPipeConnectionPoolSize="512"
maxNamedPipePooledConnectionAge="30000"
asyncCompletionThreadCount="0"
initialRequestBufferSize="4096"
maxRequestBufferSize="65536"
uncFileChangesPollingInterval="5000"
gracefulShutdownTimeout="60000"
loggingEnabled="true"
logDirectory="iisnode"
debuggingEnabled="true"
debugHeaderEnabled="false"
debuggerPortRange="5058-6058"
debuggerPathSegment="debug"
maxLogFileSizeInKB="128"
maxTotalLogFileSizeInKB="1024"
maxLogFiles="20"
devErrorsEnabled="true"
flushResponse="false"
enableXFF="false"
promoteServerVars=""
configOverrides="iisnode.yml"
watchedFiles="web.config;*.js"
nodeProcessCommandLine="C:\Program Files\nodejs\node.exe"/>
<!--
Before the handlers element can work on IIS 8.5
follow steps listed here https://github.com/tjanczuk/iisnode/issues/52
-->
<handlers>
<add name="iisnode" path="server.js" verb="*" modules="iisnode"/>
<!-- Uncomment below handler if using Socket.io -->
<!--<add name="iisnode-socketio" path="server.js" verb="*" modules="iisnode" />-->
</handlers>
<rewrite>
<rules>
<!-- Don't interfere with requests for node-inspector debugging -->
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^server.js\/debug[\/]?"/>
</rule>
<!-- First we consider whether the incoming URL matches a physical file in the /public folder -->
<rule name="StaticContent" patternSyntax="Wildcard">
<action type="Rewrite" url="public/{R:0}" logRewrittenUrl="true"/>
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
</conditions>
<match url="*.*"/>
</rule>
<!-- All other URLs are mapped to the Node.js application entry point -->
<rule name="DynamicContent">
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
</conditions>
<action type="Rewrite" url="server.js"/>
</rule>
<rule name="SocketIO" patternSyntax="ECMAScript">
<match url="socket.io.+"/>
<action type="Rewrite" url="server.js"/>
</rule>
</rules>
</rewrite>
<directoryBrowse enabled="false"/>
</system.webServer>
</configuration>
Here is the general structure of my server.js file :
var http = require('http');
var express = require('express');
var fs = require("fs");
var sql = require("mssql");
var bodyParser = require('body-parser'); // Used to parse incoming messages
var Connection = require('tedious').Connection; // Added for Azure
var app = express();
var port = process.env.port || 1337;
// pulls the index.html file
app.use(express.static(__dirname + "/"));
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
// DATABASE configuration
var config = {
userName: 'USERNAME',
password: 'PASSWORD',
server: 'SERVER',
options: {
encrypt: true,
database: 'DATABASE',
rowCollectionOnRequestCompletion: true
}
};
var connection = new Connection(config);
// Server that listens to port 80
var server = http.createServer();
var server = app.listen(port, function () {
var host = server.address().address
var port = server.address().port
console.log("Node Js app listening at http://%s:%s", host, port)
});
app.post('/postrequest', function (req, res) {
// function
});
Thanks for the help. I can't seem to figure out this issue.
I make post requests in a separate script that is in a separate folder in this directory called scripts:
xhttp.open("POST", "http://localhost:80/My Application/postrequest", false);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send("date=" + date + "&name=" + name + "&type=" + type);
I was able to successfully publish my Node Web Application to IIS by using the following configuration in my Web.Config :
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="iisnode" path="server.js" verb="*" modules="iisnode" />
</handlers>
<rewrite>
<rules>
<!-- Don't interfere with requests for node-inspector debugging -->
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^server.js\/debug[\/]?"/>
</rule>
<!-- First we consider whether the incoming URL matches a physical file in the /public folder -->
<rule name="StaticContent" patternSyntax="Wildcard">
<action type="Rewrite" url="public/{R:0}" logRewrittenUrl="true"/>
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
</conditions>
<match url="*.*"/>
</rule>
<!-- All other URLs are mapped to the Node.js application entry point -->
<rule name="DynamicContent">
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
</conditions>
<action type="Rewrite" url="server.js"/>
</rule>
<rule name="SocketIO" patternSyntax="ECMAScript">
<match url="socket.io.+"/>
<action type="Rewrite" url="server.js"/>
</rule>
</rules>
</rewrite>
<iisnode promoteServerVars="LOGON_USER" />
</system.webServer>
</configuration>
AND by changing my server.js file to :
var http = require('http');
var express = require('express');
var bodyParser = require('body-parser'); // Used to parse incoming messages
var port = process.env.port;
var app = express(function(req, res){
username = req.headers['x-iisnode-auth_user'];
});
app.use(express.static(__dirname + "/ApplicationNameOnIIS/"));
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
// Start listening on server port
app.listen(process.env.PORT);
app.get('/ApplicationNameOnIIS/', function(req, res) {
res.sendfile(__dirname + '/index.html');
});
// ...The Rest Of My Code...