Disable directory browsing in Nodejs, Azure - node.js

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>

Related

Serve Angular client and Express Sever on IIS without breaking urls

I used angular on the client-side, and nodejs on server-side, when running them using webstorm IDE they behave as expected but now I'm trying to put them on is and I'm encountering some troubles.
My main goal is to make just the client and server work together so if you have another suggestion which I have not tried, please comment.
In the IIS I had to put both server and client under the same URL (obviously) so I have deployed my angular app and copied the content of the dist folder into folder name "wwwroot" to my server (express).
Here is my code:
app.js files:
app.use(express.static(__dirname + '/wwwroot'));
app.post('/home', (req, res) => {
// some content here
});
app.get('/home', (req, res) => {
// some content here
});
const server = http.createServer(app);
server.listen(port, () => console.log('Listening to port: ' + port));
my web.config file:
<configuration>
<system.webServer>
<handlers>
<add name="iisnode" path="app.js" verb="*" modules="iisnode" />
</handlers>
<rewrite>
<rules>
<rule name="nodejs">
<match url="(.*)" />
<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>
Now, it would work just fine but I have 1 main problem which I can't solve when I'm trying to reload a page via a URL,
e.g. "http://www.automationcompare.com:4040/home;urlId=23119.06799149191"
then I get: Cannot GET /home;urlId=23119.06799149191.
I think the server should be set up to return the base HTML page no matter the url. You need to use url rewrite rule like below sample:
<system.webServer>
<rewrite>
<rules>
<rule name="Angular Routes" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="./index.html" />
</rule>
</rules>
</rewrite>
</system.webServer>
For further information about your problem, you can refer to this post. I think it is similar to your problem.

URL Rewrite not working - React SPA on Azure Web App (node)

I'm running a create-react-app build on an Azure Web App (node LTS). The app uses React Routes, and runs great from the index screen and as long as you are navigating the route links through the app. However, if you refresh a page, or navigate directly to a non-root route, you get 404. It seems to me like my web.config rewrite (of which I've tried many variations) is not being honored. I'm sure I'm just missing something obvious. Any suggestions?
index.js file
var express = require('express');
var server = express();
var options = {
index: 'index.html'
};
server.use('/', express.static('/home/site/wwwroot', options));
server.listen(process.env.PORT);
web.config (edit with updated version)
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<webSocket enabled="false" />
<handlers>
<add name="iisnode" path="index.js" verb="*" modules="iisnode"/>
</handlers>
<rewrite>
<rules>
<rule name="React Routes">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="True"/>
<add input="{REQUEST_URI}" pattern="/api" negate="true" />
</conditions>
<action type="Rewrite" url="/index.html" />
</rule>
</rules>
</rewrite>
<security>
<requestFiltering>
<hiddenSegments>
<remove segment="bin"/>
</hiddenSegments>
</requestFiltering>
</security>
<httpErrors existingResponse="PassThrough" />
</system.webServer>
</configuration>
File Structure (/site/wwwroot/)
index.html
web.config
static/ (css, js)

IIS & HapiJS error : 404 on trying to serve static files

So, I'm hosting a hapijs application on Windows server.
Everything worked okay until I had the need to serve some static files (my front-end) from my hapijs application.
I added a simple route:
// Index
server.route({
method: 'GET',
path: '/dist',
options: {
cors: {
origin: ['*'],
},
},
handler(request, h) {
server.log('info', `GET - ${request.url.path}`);
return h.file(__dirname + '/dist/index.html')
},
});
and this works okay.
But for the assets (located in the same folder), nothing to do, I can't make it work. I tried the following things:
server.route({
method: 'GET',
path: '/assets/{filename}',
options: {
cors: {
origin: ['*'],
},
},
handler(request, h) {
server.log('info', `GET - ${request.url.path}`);
return h.file(`${__dirname}/dist/assets/${request.params.filename}`)
},
});
and
server.route({
method: 'GET',
path: '/assets/{filename}.js',
options: {
cors: {
origin: ['*'],
},
},
handler(request, h) {
server.log('info', `GET - ${request.url.path}`);
return h.file(`${__dirname}/dist/assets/${request.params.filename}.js`)
},
});
And some other flavours of it. Until I realized that it is actually IIS and not the hapijs that returns a 404.
So here is my web.config file :
<configuration>
<system.webServer>
<handlers>
<remove name="OPTIONSVerbHandler" />
<add name="iisnode" path="server.js" verb="GET,POST,OPTIONS" modules="iisnode" />
<add name="OPTIONSVerbHandler" path="*" verb="OPTIONS" modules="iisnode" />
</handlers>
<rewrite>
<rules>
<rule name="DynamicContent">
<match url=".*" />
<action type="Rewrite" url="server.js" />
</rule>
</rules>
<outboundRules>
<rule name="Set-Access-Control-Allow-Origin for known origins">
<match serverVariable="RESPONSE_Access-Control-Allow-Origin" pattern=".+" negate="true" />
<action type="Rewrite" value="*" />
</rule>
</outboundRules>
</rewrite>
<httpErrors existingResponse="PassThrough" />
<security>
<requestFiltering>
<hiddenSegments>
<add segment="node_modules" />
</hiddenSegments>
</requestFiltering>
</security>
<iisnode nodeProcessCommandLine=""C:\Program Files (x86)\nodejs\node.exe"" />
</system.webServer>
<system.web>
<httpRuntime enableVersionHeader="false" />
</system.web>
</configuration>
I tried adding a
<rule name="StaticContent">
<action type="Rewrite" url="server.js"/>
</rule>
block but that does not change anything.
In case you didn't get it yet, I am no windows server user so I'm trying to solve that problem with Google searches & al but no luck so far.
I guess my question is :
WHY does IIS try to search for a file, even though it is supposed to rewrite all path to go to my NodeJS server ???
How does it know which of my routes are good and which are not?
How to make it not search for that file?
In the end, I managed to solve the problem with the following configuration:
<configuration>
<system.webServer>
<handlers>
<add name="iisnode" path="server.js" verb="GET,POST,OPTIONS" modules="iisnode" />
</handlers>
<rewrite>
<rules>
<rule name="LogFile" patternSyntax="ECMAScript" stopProcessing="true">
<match url="iisnode"/>
</rule>
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^server.js\/debug[\/]?" />
</rule>
<rule name="DynamicContent" stopProcessing="true">
<match url="^v1.*" />
<action type="Rewrite" url="server.js"/>
</rule>
<rule name="StaticContent">
<action type="Rewrite" url="public{REQUEST_URI}"/>
</rule>
</rules>
<outboundRules>
<rule name="Set-Access-Control-Allow-Origin for known origins">
<match serverVariable="RESPONSE_Access-Control-Allow-Origin" pattern=".+" negate="true" />
<action type="Rewrite" value="*" />
</rule>
</outboundRules>
</rewrite>
<security>
<requestFiltering>
<hiddenSegments>
<add segment="node_modules" />
</hiddenSegments>
</requestFiltering>
</security>
<iisnode nodeProcessCommandLine=""C:\Program Files (x86)\nodejs\node.exe"" />
</system.webServer>
<system.web>
<httpRuntime enableVersionHeader="false" />
</system.web>
</configuration>

Azure node.js relative paths with graphql cli

I have a small node.js application acting as a graph-api created with graphql-cli.
Everything works fine on localhost, but when I try to run it in azure as a web app, I seem to have a problem with paths. The below snippet is working on localhost running npm start
const server = new GraphQLServer({
typeDefs: './src/schema.graphql',
resolvers,
context: req => ({
...req,
db: new Prisma({
typeDefs: 'src/generated/prisma.graphql',
endpoint: 'xxx',
secret: 'xxx',
debug: true,
}),
}),
})
The path to one of the .graphql-file is defined:
typeDefs: './src/schema.graphql',
Which I find a bit weird considering the folder structure where index.js is in the same folder as schema.graphql
Anyhow, this is working on localhost, but when trying to run it as an azure web app I get the following error:
No schema found for path: D:\home\site\wwwroot\src\src\schema.graphql
Since this is just a scaffolded app, I don't want to change the paths in code. I don't think they are wrong since it is working on localhost. I´m thinking that I'm missing some configuration on azure.
This is my web.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<webSocket enabled="false" />
<handlers>
<add name="iisnode" path="src/index.js" verb="*" modules="iisnode"/>
</handlers>
<rewrite>
<rules>
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^src/index.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="src/index.js"/>
</rule>
</rules>
</rewrite>
<security>
<requestFiltering>
<hiddenSegments>
<remove segment="bin"/>
</hiddenSegments>
</requestFiltering>
</security>
<httpErrors existingResponse="PassThrough" />
</system.webServer>
</configuration>
And my iisnode.yml looks just like this:
nodeProcessCommandLine: "D:\Program Files (x86)\nodejs\8.4.0\node.exe"
I´ve tried a bunch of different node versions, but I'm currently running 8.4.0 on my localhost where its working
Anyone has any ideas?
You need to move the index.js file to your root and change the web.config to:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<webSocket enabled="false" />
<handlers>
<add name="iisnode" path="index.js" verb="*" modules="iisnode"/>
</handlers>
<rewrite>
<rules>
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^index.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="index.js"/>
</rule>
</rules>
</rewrite>
<security>
<requestFiltering>
<hiddenSegments>
<remove segment="bin"/>
</hiddenSegments>
</requestFiltering>
</security>
<httpErrors existingResponse="PassThrough" />
</system.webServer>
</configuration>

How to host a service and static content in iisnode

I have my website working within express. But now I need to host it on IIS. How can I get my routing to work with IISNode?
I was able to move my static content to a /public folder (html, front end js, etc). I didn't want to do this, but got that part working.
I moved my server side logic to /server.
I had previously had .Net Web API style routing working, where my services were hosted at /api. I moved these to /server/api.
Whenever I try to request my API, I get a 404. How can I get this working with IISNode?
app.use("/api", require("./api"));
// routes/api/index.js
var router = require('express').Router();
router.use('/questionsets', require('./questionsets'));
module.exports = router;
var router = require('express').Router();
router.use('/questionsets', require('./questionsets.js'));
module.exports = router;
// routes/api/questions.js
var router = require('express').Router();
router.get('/', function (req, res) {
...
});
router.get('/:id', function (req, res) {
...
});
module.exports = router;
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<security>
<requestFiltering>
<hiddenSegments>
<remove segment="bin" />
</hiddenSegments>
</requestFiltering>
</security>
<handlers>
<add name="iisnode" path="bin/www" verb="*" modules="iisnode" />
</handlers>
<iisnode loggingEnabled="false" />
<httpErrors errorMode="Detailed" existingResponse="Replace">
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" prefixLanguageFilePath="" path="/" responseMode="ExecuteURL" />
</httpErrors>
<rewrite>
<rules>
<rule name="LogFile" patternSyntax="ECMAScript" stopProcessing="true">
<match url="iisnode" />
</rule>
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^bin\/www\/debug[\/]?" />
</rule>
<rule name="StaticContent" patternSyntax="ECMAScript" stopProcessing="true">
<match url=".*" />
<action type="Rewrite" url="{C:1}" logRewrittenUrl="true" />
<conditions>
<add input="{REQUEST_URI}" pattern=".*?\/(.*)" />
</conditions>
</rule>
<rule name="DynamicContent" patternSyntax="ECMAScript">
<match url=".*" />
<conditions>
<add input="{{REQUEST_FILENAME}}" matchType="IsFile" negate="True" />
</conditions>
<action type="Rewrite" url="server/app.js" logRewrittenUrl="true" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
Source for url rewriting configuration
You need to install Application Request Routing here , and the documentation here.
Simply putting your server side files under /server would not work.
Start your express server, let's say listenning to http://localhost:3200/ ,
route request '/' to 'localhost:3200' will just route each request to your express server.

Resources