I am setting up IISNode on IIS 7 locally on my Win7 box. I followed the instructions on the site and the samples are working fine.
I created a new website and AppPool in IIS Manager to run a brand new shell of an Express site. I've added the web.config to tie the iisnode module to my starting .js file.
When I browse to the default route (/) I get an Http 403.14 error (Server is configured to not list the contents of the directory).
I have attempted to remap the IISNode sample directory to where my Express app is and the same error occurs.
If I attempt to go to a non-existing route, I DO get Connect's 404 error message of Cannot VERB ROUTE.
I feel like I"m missing something simple and (hopefully obvious).
Has anyone ran into this and can provide me some insight? Looking online has provided little light in terms of even when I can check.
I figured out what issue I was having. In my web.config, I had the default IISNode section and the handler section to map the iisnode module to my app.js file.
However, when using Express, every route has to go through that file. So by adding the rewrite section as below it resolved my issue.
<rewrite>
<rules>
<rule name="Catch All">
<match url="/*" />
<action type="Rewrite" url="app.js" />
</rule>
</rules>
</rewrite>
For a more advanced URL rewriting configuration check out the web.config template at http://tomasz.janczuk.org/2012/05/yaml-configuration-support-in-iisnode.html. This template allows you to redirect requests for static content to the IIS static file handler, as well as retain access to iisnode logs over HTTP.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="iisnode" path="server.js" verb="*" 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="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="server.js"/>
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
The web.config above has the following effect:
It specifies server.js as the entry point to your node.js application.
It redirects all requests for URLs that map to physical files in the “public” subdirectory to an IIS static file handler. Using IIS static file handler has a large performance benefit compared to serving static content from within a node.js application. The handler leverages IIS and OS low level caching mechanisms which offer superb performance.
It allows IIS to serve the log files that capture output of a node.js application as static files such that you can access them over HTTP. By default, if your server.js entry point is reached at http://example.com/server.js, the log files would be accessible at http://example.com/iisnode.
It exposes the built-in node-inspector debugger at http://example.com/server.js/debug. Learn more about debugging with iisnode.
It sends all other HTTP requests to be processed by your node.js application in server.js.
Fin more info in my link there I have a working example a the bottom of the question
Below its the project configuration
below the code for server.js
"use strict";
var express = require('express');
// determind what mode we are
var env = process.env.NODE_ENV = process.env.NODE_ENV||'developemnt';
var app = express();
//configure the view engine
app.set('views', __dirname + '/views');
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');
//app.use('/public', express.static(__dirname + '../public'));
//the asterisk handles all routes includes javascript, css, html request...
app.get('*', function (req , res) {
res.render('index');
});
var PORT = 3030;
app.listen((process.env.PORT!==undefined)?process.env.PORT:PORT);
console.log('Listening to PORT : ' + process.env.PORT );
Below the index.html
<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
<head>
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon"/>
<base href="/">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
</head>
<body ng-app="idetikApp">
<div ng-view=""></div>
<script src="app/app.js"></script>
</body>
</html>
web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="iisnode" path="server/server.js" verb="*" 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/server.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="server/server.js"/>
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
app.js
angular.module('idetikApp', [ 'ngResource', 'ngRoute']);
angular.module('idetikApp').config(function ($routerProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$routerProvider.when('/', {templateUrl: '/partials/main', controller:'mainctrl'})
});
angular.module('idetikApp').controller('mainctrl', function ($scope) {
$scope.mayvar = "hello world"
})
and the main.html
<h1>this is a partial</h1>
<h2>{{myvar}}</h2>
and my folder structure
but now I cant find my files inside public :(
Related
My online host service smarterasp.net require some changes made to publish my angular compiled app (Angular v. 11.1.1) as a node js app. On their quickstart guide(https://www.smarterasp.net/support/kb/a1970/quick-start-node_js.aspx?KBSearchID=818443) they say: "We are Hosting node.js applications in IIS on Windows via IISNode, so you need to update listening port to use "process.env.PORT" in your code" and there's code given as an example:
HelloWorld Sample:
hello.js
var http = require('http');
http.createServer(function(req, res) {
res.writeHead(200, {
'Content-Type': 'text/plain'
});
res.end('Hello, world!');
}).listen(process.env.PORT);
web.config
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<system.webServer>
<handlers>
<add name="iisnode" path="hello.js" verb="*" modules="iisnode" />
</handlers>
<rewrite>
<rules>
<rule name="mysite">
<match url="/*" />
<action type="Rewrite" url="hello.js" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
"You do not have to run any command line with npm or node.exe to host nodejs with us." They say.
Now, the problem is: My compiled Angular app consists on many .js files, but the hello.js example given only has a string return res.end('Hello, world!');. My questions are:
What's the correct code to use in my case (instead of the hello.js) and where should I put this code? I already try to put it inside my index.html file, inside the header tags, inside a script, but the web browser console shows me the error (Uncaught ReferenceError: require is not defined).
Once I uploaded my test files, my website shows a black screen.
This is my attempt of script inside my index.html file:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>DummyTitle</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script>
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {
'Content-Type': 'text/plain'
});
res.write(req.url);
res.end();
}).listen(process.env.PORT);
</script>
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght#300;400;500&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>
<body style="background-color: black;">
<app-root></app-root>
</body>
</html>
And this is my web.config file (following the angular guide about IIS (https://angular.io/guide/deployment)):
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<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="/mainwebpage/index.html" />
</rule>
</rules>
</rewrite>
<handlers>
<add name="iisnode" path="*.js" verb="*" modules="iisnode" />
</handlers>
</system.webServer>
</configuration>
Has somebody found the same issue before? Help please!!
After a few days I figure out the quick start guide provided was wrong (https://www.smarterasp.net/support/kb/a1970/quick-start-node_js.aspx?KBSearchID=818443) I had absolutely no necesity to redirect my requests/responses to a server as suggested on the hello.js file. Probably because my angular app doesn't use server side rendering (SSR, Angular universal).
The solution was simply paste the compiled angular files at the designated folder and add a web.config. To my surprise I discover that the example of web.config file given on the official angular site (https://angular.io/guide/deployment#fallback-configuration-examples) was also wrong. Here's my web.config file, hoping it helps other poor souls looking for an inexistence documentation:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<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>
</configuration>
If you have server.js file put the code "process.env.PORT" inside the server.js file.
<configuration>
<system.webServer>
<handlers>
<add name="iisnode" path="server.js" verb="*" modules="iisnode" />
</handlers>
</system.webServer>
</configuration>
This handler registration allows the same web site to contain other *.js files (e.g. jQuery libraries) that IIS will continue serving as static files.
Reference link:
use node.js express on iis with iisnode
Good Day!
My colleague has a website node.js (next.js), his website works fine when we build and start thru console (npm run build and npm start).
We have hosted it in a Azure VM (Windows Server 2016 IIS, iisnode and urlrewrite installed), we created a pipeline and we are able to get the artifacts (".next" folder when we run the build) and deploy it to IIS however we still need a manual interaction to place the web.config. Below is the web.config
<!-- indicates that the hello.js file is a node.js application
to be handled by the iisnode module -->
<handlers>
<add name="iisnode" path="service-worker.js" verb="*" modules="iisnode" />
</handlers>
<!-- use URL rewriting to redirect the entire branch of the URL namespace
to hello.js node.js application; for example, the following URLs will
all be handled by hello.js:
http://localhost/node/express/myapp/foo
http://localhost/node/express/myapp/bar
-->
<rewrite>
<rules>
<rule name="AMS" 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="/" />
</rule>
</rules>
</rewrite>
But when we visit the website, it throws an error of 403 that need to supply the default page. (I'm lost here and not able to run his website thru IIS)
Note: His other website works fine (because it has a service-worker.js).
Anyone experience deploying the Next.JS to IIS? Thanks in Advance.
In the /public folder, create the following web.config to accept requests from /a/b/c and rewrite them to / where our NextJs code lives.
<?xml version="1.0"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="NextJs Routes" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
Just doing this should allow you to reload a page on a route like /products, but NextJs will render /, ie, the index page, because that's what our rewrite rule told it to deliver.
So, we need to create a body Component that takes a NextRouter as a prop then compare the window's url to the router's url. If they don't match, we need to change our client side route with router.push().
I'm using TypeScript so my body.tsx is
import * as React from 'react';
import { NextRouter } from 'next/router';
export default class Body extends React.Component<{router : NextRouter}>
{
componentDidMount()
{
if (window.location.pathname == this.props.router.pathname) return;
this.props.router.push(global.window.location.pathname);
}
render = () => this.props.children;
}
Then in _app.tsx, we simply need to wrap the main Component in our Body Component.
import { useRouter } from 'next/router'
import Head from 'next/head';
import Body from '../src/components/elements/body';
function MyApp({ Component, pageProps }) {
const router = useRouter();
return (
<>
<Head>
<title>NextJs on IIS</title>
</Head>
<Body router={router}>
<Component {...pageProps} />
</Body>
</>
)
}
export default MyApp
Run npm run build, and copy the /out folder to your IIS server.
I'm trying get all http traffic to redirect to https using web.config on azure. I'm using node.js stack.
I want the url to remain the same for all requests. Currently, however, it's appending server.js to the end of the route.
The problem:
Go to http://www.example.com/
Redirect to https://www.example.com/server.js
Below is my web.config file I'm using.
<?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="server.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="^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 site entry point -->
<rule name="DynamicContent">
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
</conditions>
<action type="Rewrite" url="server.js"/>
</rule>
<!-- Redirect all http traffic to https -->
<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>
<!-- '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>
Maybe you can try to install the extension named Redirect HTTP to HTTPS via the Azure portal, with this approach you have no need to add any rule for redirecting to HTTPS.
I have a Mean stack application that works now on Node Js and port 3000.
I have a Windows Server 2016 and i need to deploy .Net Apps, so i need IIS.
I can't make run both web servers on port 80 but i don't want the users are forced to type the port where running my Mean app.
I tried to work with iisnode, but with no success and i also read about reverse proxy in order to redirect the requests on the port 80 to another port.
Both solution could be valid, but, before spend other time on the wrong direction i ask what is the best practice in this case.
UPDATE:
a little step forward.
I can now access to the loading page of the app, but the application can't locate my bundle.js (the package created by Webpack).
module.exports = webpackMerge.smart(commonConfig, {
entry: {
'app': './assets/app/main.aot.ts'
},
output: {
path: path.resolve(__dirname + '/public/js/app'),
filename: 'bundle.js',
publicPath: '/js/app/',
chunkFilename: '[id].[hash].chunk.js'
},
My web.config is:
<configuration>
<system.webServer>
<handlers>
<add name="iisnode" path="start.js" verb="*" modules="iisnode" />
</handlers>
<rewrite>
<rules>
<rule name="tep">
<match url="/*" />
<action type="Rewrite" url="start.js" />
</rule>
</rules>
</rewrite>
<security>
<requestFiltering>
<hiddenSegments>
<add segment="node_modules" />
</hiddenSegments>
</requestFiltering>
</security>
</system.webServer>
</configuration>
An extract of start.js file:
var app = require('./app');
var debug = require('debug')('node-rest:server');
var http = require('http');
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
var server = http.createServer(app);
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
And the view (hbs):
<!DOCTYPE html>
<html>
<head>
<base href="/tep">
<title>Tennis Events Pro</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<tep-app>Loading...</tep-app>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="/tep/bundle.js"></script>
</body>
</html>
I worked around adjusting configuration and paths, with no result...
Thanks
Max
Reverse proxy with ARR module for IIS will best way to achieve what you want.
You need to install URL Rewrite and ARR module for IIS
Enable ARR. On the Application Request Routing page, select Enable proxy
Create Website in IIS Manager
Create web.config in this website folder
<?xml version="1.0" encoding="UTF-8"?><configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="rewrite to 3000" stopProcessing="true">
<match url="(.*)" />
<action type="Rewrite" url="http://127.0.0.1:3000/{R:1}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
After that steps IIS will proxy your requests to port 3000
What is wrong with my setup? have in mind I use express.
web.config file :
<handlers>
<add name="iisnode" path="app.js" verb="*" modules="iisnode" />
</handlers>
<rewrite>
<rules>
<rule name="myapp">
<match url="/*" />
<action type="Rewrite" url="app.js" />
</rule>
</rules>
</rewrite>
and the app.js is as below :
var express = require('express');
var app = express();
var server = http.createServer(app).listen(process.env.port);
app.use(express.static(__dirname + '/pro/Public'));
app.get('/pro',function(req,res) {
res.sendfile(__dirname + '/yoyo.html');
res.end;
});
and the html has the classic layout like this:
<link rel="stylesheet" type="text/css" href="cssKtelVolouOsm.css">
<script type="text/javascript" src="javascriptKtelVolouOsm.js"></script>
and I get the following errors:
Failed to load resource: the server responded with a status of 404 (Not Found) http://localhost/cssKtelVolouOsm.css
Failed to load resource: the server responded with a status of 404 (Not Found) http://localhost/javascriptKtelVolouOsm.js
If those files actually exist under ./pro/Public then this is most likely caused by the use of relative URLs in your html. Try this instead.
<link rel="stylesheet" type="text/css" href="/cssKtelVolouOsm.css">
<script type="text/javascript" src="/javascriptKtelVolouOsm.js"></script>