I have an app service in my azure account, Which is running a node application (Express, Angular and websockets). I am able to serve static contents to my users but the REST APIs are failing with 404 not found error.
Following is my code in my index.js
var os = require('os');
var fs = require("fs");
var bodyParser = require('body-parser');
var express = require('express'),
expressApp = express(),
socketio = require('socket.io'),
http = require('http'),
uuid = require('node-uuid'),
config = require('../config/config.json');
var httpServer = http.createServer(expressApp),
rooms = {},
userIds = {};
expressApp.use(express.static(__dirname + '/../public/dist/'));
expressApp.use(bodyParser.urlencoded({ extended: true }));
expressApp.use(bodyParser.json());
var router = express.Router();
expressApp.use('/api', router);
router.get('/getsomethings', function(req, res) {
res.json(something);
});
expressApp.use('/api', router);
expressApp.listen = function listen() {
httpServer.listen(config.PORT);
};
expressApp.listen();
exports.run = function(config) {
//some code
};
And following is my web.config for app.service
<configuration>
<system.webServer>
<handlers>
<!-- indicates that the app.js file is a node.js application to be handled by the iisnode module -->
<add name="iisnode" path="index.js" verb="*" modules="iisnode" />
</handlers>
<rewrite>
<rules>
<!-- Don't interfere with requests for node-inspector debugging -->
<clear />
<rule name="Redirect to https" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Permanent" appendQueryString="false" />
</rule>
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^index.js\/debug[\/]?" />
</rule>
<!-- First we consider whether the incoming URL matches a physical file in the /public folder -->
<rule name="StaticContent">
<action type="Rewrite" url="public{REQUEST_URI}" />
</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="index.js" />
</rule>
</rules>
</rewrite>
<security>
<requestFiltering>
<hiddenSegments>
<add segment="node_modules" />
</hiddenSegments>
</requestFiltering>
</security>
<!-- You can control how Node is hosted within IIS using the following options -->
<!--<iisnode
node_env="%node_env%"
nodeProcessCountPerApplication="1"
maxConcurrentRequestsPerProcess="1024"
maxNamedPipeConnectionRetry="3"
namedPipeConnectionRetryDelay="2000"
maxNamedPipeConnectionPoolSize="512"
maxNamedPipePooledConnectionAge="30000"
asyncCompletionThreadCount="0"
initialRequestBufferSize="4096"
maxRequestBufferSize="65536"
watchedFiles="*.js"
uncFileChangesPollingInterval="5000"
gracefulShutdownTimeout="60000"
loggingEnabled="true"
logDirectoryNameSuffix="logs"
debuggingEnabled="true"
debuggerPortRange="5058-6058"
debuggerPathSegment="debug"
maxLogFileSizeInKB="128"
appendToExistingLog="false"
logFileFlushInterval="5000"
devErrorsEnabled="true"
flushResponse="false"
enableXFF="false"
promoteServerVars=""
/>-->
</system.webServer>
</configuration>
When I access my site Everything is working fine except that /getsomethings XHR is giving 404 error. All static contents are served fine.
Can anyone help me to figure out what is wrong?
You say "I am able to serve static contents to my users", because you have this in web.config.
<!-- First we consider whether the incoming URL matches a physical file in the /public folder -->
<rule name="StaticContent">
<action type="Rewrite" url="public{REQUEST_URI}" />
</rule>
Based on the code you provided above, please make sure your folder structure looks like:
D:\home\site
├── config
│ └── config.json
├── deployments
│ └── ...
├── locks
│ └── ...
├── Diagnostics
│ └── ...
├── public
│ └── dist
│ └── ...
└── wwwroot
├── node_modules
│ └── ...
├── index.js
├── package.json
└── web.config
Also, Please try changing the following line of code:
httpServer.listen(config.PORT);
to:
httpServer.listen(process.env.PORT || config.PORT);
Related
I have developed a full-stack application with Vue 2, Node , Express and Postgres.
I could deploy the application to Azure , and the system coming up, but when I try to do register user with Register page that I have created , I get " POST … 500 (Internal Server Error) ", **as I have tried with Postman , there is no issue in saving user data with same post controller ** .
Notice that I have set BaseURL to ‘’ in Api.js ( Client ):
import axios from ‘axios’
import store from ‘#/store/store’
export default () => {
return axios.create({
baseURL: ‘’,
headers: {
Authorization: Bearer ${store.state.token}
}
})
}
this is Register controller in /Controller folder :
//Registering user
async register(req, res) {
const hash = bcrypt.hashSync(req.body.password, 10);
try {
const user = await User.create(
Object.assign(req.body, { password: hash })
);
const userJson = user.toJSON();
res.send({
user: userJson,
token: jwtSignUser(userJson),
});
} catch (err) {
res.status(500).send({
error: There is error in registering: ${err},
});
}
},
I have added the following web.config file in dist folder, but it doesn't resolve the issue :
<configuration>
<system.webServer>
<staticContent>
<mimeMap fileExtension="woff" mimeType="application/font-woff" />
<mimeMap fileExtension="woff2" mimeType="application/font-woff" />
</staticContent>
<rewrite>
<rules>
<clear />
<rule name="Redirect to https" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" redirectType="Permanent" appendQueryString="false" />
</rule>
</rules>
</rewrite>
<httpErrors>
<remove statusCode="404" subStatusCode="-1" />
<remove statusCode="500" subStatusCode="-1" />
<error statusCode="404" path="/survey/notfound" responseMode="ExecuteURL" />
<error statusCode="500" path="/survey/error" responseMode="ExecuteURL" />
</httpErrors>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
Could you please let me know how I could resolve the issue .
I have deployed node api in IIS & https is binded to 443 port.
In the code, I'm using process.env.PORT || 446.
When I browse, I couldn't get the response from https://localhost:443 instead I'm getting it from https://localhost:446
server.js
var https = require('https');
var fs = require('fs');
var options = {
pfx : fs.readFileSync('./secure.pfx'),
passphrase : 'secure'
}
var app = require('./app')
var port = process.env.PORT || 446
var server = https.createServer(options,app)
server.listen(port)
webconfig.js
<configuration>
<system.webServer>
<!-- indicates that the hello.js file is a node.js application
to be handled by the iisnode module -->
<handlers>
<add name="iisnode" path="server.js" verb="*" modules="iisnode" />
</handlers>
<rewrite>
<rules>
<rule name="sendToNode">
<match url="/*" />
<action type="Rewrite" url="server.js" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
It doesn't run on the bound port but always take 446.
I am trying to upload file from client which is in react to node server which is hosted on Azure web app
Application logs on azure show me this error "This error means that the request sent to the Web server contained an HTTP verb that is not allowed by the configured module handler for the request"
web.config
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<webSocket enabled="false" />
<handlers>
<!-- indicates that the app.js file is a node.js application to be handled by the iisnode module -->
<add name="iisnode" path="server.js" verb="*" modules="iisnode" />
</handlers>
<rewrite>
<rules>
<!-- Don't interfere with requests for logs -->
<rule name="LogFile" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^[a-zA-Z0-9_\-]+\.js\.logs\/\d+\.txt$" />
</rule>
<!-- 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">
<action type="Rewrite" url="public{REQUEST_URI}" />
</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>
</rules>
</rewrite>
<!-- You can control how Node is hosted within IIS using the following options -->
<!--<iisnode
node_env="%node_env%"
nodeProcessCommandLine=""%programfiles%\nodejs\node.exe""
nodeProcessCountPerApplication="1"
maxConcurrentRequestsPerProcess="1024"
maxNamedPipeConnectionRetry="3"
namedPipeConnectionRetryDelay="2000"
maxNamedPipeConnectionPoolSize="512"
maxNamedPipePooledConnectionAge="30000"
asyncCompletionThreadCount="0"
initialRequestBufferSize="4096"
maxRequestBufferSize="65536"
watchedFiles="*.js"
uncFileChangesPollingInterval="5000"
gracefulShutdownTimeout="60000"
loggingEnabled="true"
logDirectoryNameSuffix="logs"
debuggingEnabled="true"
debuggerPortRange="5058-6058"
debuggerPathSegment="debug"
maxLogFileSizeInKB="128"
appendToExistingLog="false"
logFileFlushInterval="5000"
devErrorsEnabled="true"
flushResponse="false"
enableXFF="false"
promoteServerVars=""
/>-->
</system.webServer>
</configuration>
Updated : Code
var express = require("express");
var multer = require('multer');
var router = express.Router();
var logwrite = require('./logwrite');
var storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, __dirname);
},
filename: function (req, file, callback) {
callback(null, 'aasasa-' + Date.now());
}
});
var upload = multer({ storage : storage}).single('userPhoto');
router.post("/upload", function(req,res){
// res.send(" we got it !!")
upload(req,res,function(err) {
if(err) {
return res.end("Error uploading file.");
}
else{
res.end("File is uploaded" + __dirname);
}
});
});
module.exports = router;
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:
500.1000 ERROR
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:
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...
What is the proper way to convert this lines to IIS web.config? I am trying to use Backbone Router with history support. It works perfect with .htaccess but i have no idea about how to do this on IIS.
.htaccess file
# html5 pushstate (history) support:
<ifModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !index
RewriteRule (.*) index.html [L]
</ifModule>
this is the script included in index.html
$(document).ready(function(){
var AppRouter = Backbone.Router.extend({
routes: {
'': 'home',
'about(/)': 'about', //about or /about/ will call the same function
'work(/:id)' : 'work',
"*path" : "notFound"
}
});
// Initiate the router
var app_router = new AppRouter;
app_router.on('route:home', function() {
$("#log").html("home");
});
app_router.on('route:about', function() {
$("#log").html("about");
});
app_router.on('route:work', function(id) {
$("#log").html("work " + id);
});
app_router.on('route:notFound', function(path) {
$("#log").html("404 " + path);
});
Backbone.history.start({pushState: true, root: "/post43/"});
$(document).on("click", "a:not([data-bypass])", function(e) {
// Get the anchor href and protcol
var href = $(this).attr("href");
// Stop the default event to ensure the link will not cause a page refresh.
e.preventDefault();
Backbone.history.navigate(href, true);
});
});
After some digging, this piece of code works on IIS for me. I was looking this guide when converting my htaccess. I hope it will help others who are looking for this kind of solution.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="history" stopProcessing="true">
<match url="(.*)" ignoreCase="false" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />
<add input="{URL}" pattern="^index$" ignoreCase="false" negate="true" />
</conditions>
<action type="Rewrite" url="index.html" appendQueryString="true" />
</rule>
</rules>
</rewrite>
<defaultDocument>
<files>
<remove value="index.html" />
<add value="index.html" />
</files>
</defaultDocument>
</system.webServer>
</configuration>