Hosting node js website to Azure. Default path / not working - node.js

I have a node js website which I am deploying to the azure server using visual studio code. The following is my code at server.js
var express =require('express');
var bodyParser=require("body-parser")
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
var nodemailer = require("nodemailer");
var port=process.env.PORT || 3000;
app.use(express.static(__dirname + '/public'));
app.get('/',function(req,res){
console.log('hello from server');
res.render('./public/index.html');
});
I deployed the website to an azure app service and the url always expects the index.html to be added to it to work. for e.g https://abc.azurewebsites.net does not work but https://abc.azurewebsites.net/index.html works. How do I remove the index.html from the url?
My azure folder structure is site/wwwroot/public/all html files.
Can anyone please suggest a solution

Update:
web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<webSocket enabled="false" />
<rewrite>
<rules>
<rule name="DynamicContent">
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
</conditions>
<action type="Rewrite" url="public/index.html"/>
</rule>
</rules>
</rewrite>
<security>
<requestFiltering>
<hiddenSegments>
<remove segment="bin"/>
</hiddenSegments>
</requestFiltering>
</security>
<httpErrors existingResponse="PassThrough" />
</system.webServer>
</configuration>
Original Answer:
Just add a file named .htaccess to the root directory('/site/wwwroot'), and this is the content of the file:
DirectoryIndex public/index.html
After that, default of your web app will change to 'public/index.html'.

Related

HTTP ERROR 400.605. Deploying NodeJS app on IIS

I've got error during deploying my app to IIS Server. I use URL Rewrite and IISNode. I gave all permissions to IUSR and IIS_IUSRS, and I went throught a lot of errors, but I can't go through this one. I will be very grateful for your help.
I've got this error
My web.config file looks like:
<configuration>
<system.webServer>
<handlers>
<add name="iisnode" path="src/app.js" verb="*" modules="iisnode" />
</handlers>
<rewrite>
<rules>
<rule name="app">
<match url="/*" />
<action type="Rewrite" url="src/app.js" />
</rule>
<rule name="ReverseProxyInboundRule1" stopProcessing="true">
<match url="(.*)" />
<action type="Rewrite" url="http://localhost:8080/{R:1}" />
</rule>
</rules>
</rewrite>
<security>
<requestFiltering>
<hiddenSegments>
<add segment="node_modules" />
</hiddenSegments>
</requestFiltering>
</security>
</system.webServer>
</configuration>
My app.js file looks like:
const express = require('express');
const cors = require('cors');
const app = express();
app.get('/', (req, res, status)=>{
return res.status(200).json({
"message": "Hello world!"
});
});
app.use(cors());
app.use(express.json());
app.listen(8080, () => {
console.log('App listening on port 8080')
});
From the analysis of the error information, it can be determined that the problem is caused by the abnormal request of the ARR module, mainly because of the syntax error of the URL rewriting rule, which will cause this 400.605 error. It is recommended to use the exclusion method, first disable all ARR rules, and then gradually sort out the rules with grammar problems.
Here is the same question you can use as a reference: ARR The request cannot be routed because it has reached the Max-Forwards limit. The server may be self-referencing itself in request routing topology.

Disable directory browsing in Nodejs, Azure

I'm trying to disable directory browsing in node, hosted on Azure.
This is my root folder and I want to disable browsing.
The following is my index.js file
const express = require('express');
const publicweb = './';
const app = express();
app.use(express.static(publicweb));
app.disable('x-powered-by');
console.log(`serving ${publicweb}`);
app.get('*', (req, res) => {
res.sendFile(`index.html`, { root: publicweb });
});
const port = process.env.PORT || '3500';
app.listen(port, () => console.log(`API running on localhost:${port}`));
I do not want the files to be accessible from the front-end application.
You can try by creating a web.config, under the hood Azure uses IIS to serve your app
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<webSocket enabled="false" />
<handlers>
<add name="iisnode" path="app.js" verb="*" modules="iisnode"/>
</handlers>
<rewrite>
<rules>
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^app.js\/debug[\/]?" />
</rule>
<rule name="StaticContent">
<action type="Rewrite" url="public{REQUEST_URI}"/>
</rule>
<rule name="DynamicContent">
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
</conditions>
<action type="Rewrite" url="app.js"/>
</rule>
</rules>
</rewrite>
<security>
<requestFiltering>
<hiddenSegments>
<remove segment="bin"/>
</hiddenSegments>
</requestFiltering>
</security>
<httpErrors existingResponse="PassThrough" />
<iisnode watchedFiles="web.config;*.js" debuggingEnabled="false" />
</system.webServer>
</configuration>

Deploy multiple node.js applications into one web application fails

I read that a deployment of many node.js applications in one azure web app is possible. So I wanted to try it. I created three node.js applications using express, and placed them as following:
TestApplication
-testapp0
node_modules
index.js
package.json
package-lock.json
web.config
-testapp1
node_modules
index.js
package.json
package-lock.json
web.config
-testapp2
node_modules
index.js
package.json
package-lock.json
web.config
Every index.js has almost the exact same code. The output is the only thing that changes.
In the web.config I changed the names of the handlers and rules.
index.js
const express = require("express");
const app = express();
app.get("/", (_, res)=>{
res.status(200).send("Welcome to TestApp0"); // testapp1: Welcome to TestApp1, testapp2: Welcome to TestApp2
});
app.get("/test", (_, res)=>{
res.status(200).send("TestApp0 TestPath"); //testapp1: TestApp1 TestPath, testapp2: TestApp2 TestPath
});
const PORT = process.env.PORT || 1337;
app.listen(PORT, () => console.log(`Listening to http://localhost:${PORT}`));
web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<webSocket enabled="false" />
<handlers>
<!-- name="iisnode1" for testapp1 and name="iisnode2" for testapp -->
<add name="iisnode0" path="index.js" verb="*" modules="iisnode"/>
</handlers>
<rewrite>
<rules>
<!-- name="NodeInspector1" for testapp1 and name="NodeInspector2" for testapp -->
<rule name="NodeInspector0" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^index.js\/debug[\/]?" />
</rule>
<!-- name="StaticContent1" for testapp1 and name="StaticContent2" for testapp -->
<rule name="StaticContent0">
<action type="Rewrite" url="public{REQUEST_URI}"/>
</rule>
<!-- name="DynamicContent1" for testapp1 and name="DynamicContent2" for testapp -->
<rule name="DynamicContent0">
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
</conditions>
<action type="Rewrite" url="index.js"/>
</rule>
</rules>
</rewrite>
<security>
<requestFiltering>
<hiddenSegments>
<remove segment="bin"/>
</hiddenSegments>
</requestFiltering>
</security>
<httpErrors existingResponse="PassThrough" />
</system.webServer>
</configuration>
Once I had the code ready, I deployed the File TestApplication to Azure using the Azure App Service extension in VSCode.
Before that I took care to change the Settings of "Path Mapping":
| virtueller Pfad | Physischer Pfad | Typ |
---------------------------------------------------------
| / | site\wwwroot\testapp0 | Application |
| /testapp1 | site\wwwroot\testapp1 | Application |
| /testapp2 | site\wwwroot\testapp2 | Application |
When I start the application I go, as desired, straight to testapp0 and when I enter the "/test" path, it shows me the desired output "TestApp0 TestPath".
I wanted to see in the screen the following:
"Welcome to TestApp0" when I go to "/" it works
"TestApp0 TestPath" when I go to "/test" it works
"Welcome to TestApp1" when I go to "/testapp1" instead I get "Cannot GET /testapp1"
"TestApp1 TestPath" when I go to "/testapp1/test" instead I get "Cannot GET /testapp1/test"
"Welcome to TestApp2" when I go to "/testapp2" instead I get "Cannot GET /testapp2"
"TestApp2 TestPath" when I go to "/testapp2/test" instead I get "Cannot GET /testapp2/test"
I tried to look everywhere for a way to achieve this. But sadly I haven't found a solution that worked and there is not much literature that I can read.
I assume that this isn't working because the node application (testapp0) looks for a path that is called "/testapp1" and there isn't any. That is why I get the "Cannot get" Error. But I want to switch to the other node application (testapp1) as soon as I enter "/testapp1" and then with "/testapp1/test" get the desired output. What am I doing wrong? I haven't found anything helpful and I am new to Azure. That is why guidance would be appreciated.
Thank you for your time!

Node.js Express app only works via localhost, does not work over network (File or Directory not found)?

I am trying to create a node.js express app that is supposed to sit on an IIS server and be hit over the internet. However, I have only been able thus far to get this working via localhost. My node.js app works when accessing it via localhost on both my local machine and through IIS on a Windows Server 2012 R2 machine, but attempting to access via a URL or IP returns with the following page:
I am not sure exactly what is going on but I have been banging my head over this for the past day. If someone has any idea and could shed some light on this it would be greatly appreciated.
Here is my app.js (.env file does not contain variables for PORT or IP and is only used for keys)
var express = require('express');
var app = express();
var router = require('./routes/index.js');
var bodyParser = require('body-parser');
var dotenv = require('dotenv');
dotenv.config();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:false}));
app.use(router);
var port = process.env.PORT;
var ip = process.env.IP;
app.listen(process.env.PORT, process.env.IP, () => {
console.log(`Server running on ${process.env.IP}:${process.env.PORT}`);
});
index.js for routing
var express = require('express');
var router = express.Router();
var sfdcSystemController = require('../controllers/Salesforce/SystemController.js');
var jwt = require('jsonwebtoken');
var fs = require('fs');
router.get('/',sfdcSystemController.doGet);
module.exports = router;
web.config for iisnode
<configuration>
<system.webServer>
<handlers>
<add name="iisnode" path="app.js" verb="*" modules="iisnode" />
</handlers>
<rewrite>
<rules>
<rule name="nodejs">
<match url="api/*" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
</conditions>
<action type="Rewrite" url="/app.js" />
</rule>
</rules>
</rewrite>
<security>
<requestFiltering>
<hiddenSegments>
<add segment="node_modules" />
<add segment="iisnode" />
</hiddenSegments>
</requestFiltering>
</security>
</system.webServer>
</configuration>
Figured out my problem. Turns out it was more of a problem with IIS and how it was configured on the server vs what my code was doing.
In IIS, I had to do the following to get my node.js app working...
Update Anonymous Authentication, make sure it was enabled, and to give my App Pool Identity access to it instead of a server user.
Update Error Page Feature Settings to "Detail Errors"
Give my new node.js app its own IP instead of requiring a host header.

HTTPS issues in azure

I imported the git socket.io chat room project! The code works normally with http = require ('http') but when exchanging for https = require ('https') my server responds with error 500 http
var express = require('express')
, app = express()
// , http = require('http')
, https = require('https')
, fs = require('fs')
, privateKey = fs.readFileSync('HTTPS_Permissions/key.key', 'utf8')
, certificate = fs.readFileSync('HTTPS_Permissions/cert.cert', 'utf8')
, credentials = {key: privateKey, cert: certificate}
, httpsServer = https.createServer(credentials, app)
// , httpServer = http.createServer(app)
, io = require('socket.io').listen(httpsServer)
//, port = process.env.PORT || 8080
, port = process.env.PORT
httpsServer.listen(port, function () {
console.log('Server listening on port %d', port);
});
//httpServer.listen(port);
// routing
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
I followed the project you shared in the comment,it works on my side.
web.config
<?xml version="1.0" encoding="utf-8"?>
<!--
This configuration file is required if iisnode is used to run node processes behind
IIS or IIS Express. For more information, visit:
https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config
-->
<configuration>
<system.webServer>
<!-- Visit http://blogs.msdn.com/b/windowsazure/archive/2013/11/14/introduction-to-websockets-on-windows-azure-web-sites.aspx for more information on WebSocket support -->
<webSocket enabled="false" />
<handlers>
<!-- Indicates that the server.js file is a node.js site to be handled by the iisnode module -->
<add name="iisnode" path="app.js" verb="*" modules="iisnode"/>
</handlers>
<rewrite>
<rules>
<!-- Do not interfere with requests for node-inspector debugging -->
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^app.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 site entry point -->
<rule name="DynamicContent">
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
</conditions>
<action type="Rewrite" url="app.js"/>
</rule>
</rules>
</rewrite>
<!-- 'bin' directory has no special meaning in node.js and apps can be placed in it -->
<security>
<requestFiltering>
<hiddenSegments>
<remove segment="bin"/>
</hiddenSegments>
</requestFiltering>
</security>
<!-- Make sure error responses are left untouched -->
<httpErrors existingResponse="PassThrough" />
<!--
You can control how Node is hosted within IIS using the following options:
* watchedFiles: semi-colon separated list of files that will be watched for changes to restart the server
* node_env: will be propagated to node as NODE_ENV environment variable
* debuggingEnabled - controls whether the built-in debugger is enabled
See https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config for a full list of options
-->
<iisnode watchedFiles="web.config;*.js"/>
</system.webServer>
</configuration>
If you throw the index.html into public folder which is created by yourself under wwwroot/ directly, you need to add the below code into your code based on this article.
app.use(express.static('public'))
I tested for that.
Update Answer:
I also turn on the Web Sockets Option.

Resources