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!
Related
I've tried to get the following code running on a Windows App Service on Azure:
const http = require('http');
const server = http.createServer((request, response) => {
response.setHeader('Content-Type', 'text/event-stream');
response.setHeader('Cache-Control', 'no-cache');
response.setHeader('Connection', 'keep-alive');
response.setHeader('Transfer-Encoding', 'chunked');
response.flushHeaders();
var interval = setInterval(function () {
response.write("data: extra data\n\n");
}, 1000);
request.on('close', function () {
clearInterval(interval);
})
});
const port = process.env.PORT || 1337;
server.listen(port);
console.log("Server running at http://localhost:%d", port);
It works when I run it locally, however does not when deployed to the App Service.
My web.config looks like as follows:
<?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" responseBufferLimit="0"/>
</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{PATH_INFO}"/>
</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"/>-->
<iisnode flushResponse="true" />
</system.webServer>
</configuration>
I've added in <iisnode flushResponse="true" /> and responseBufferLimit="0" as per suggestions from the Microsoft App Service docs: https://learn.microsoft.com/en-us/azure/app-service/app-service-web-nodejs-best-practices-and-troubleshoot-guide#flushresponse but still to no avail.
Your project can run locally, that is, through the command line npm start, npm run dev, etc. to start webapp in local. At this time, the web.config file will not be used. Unless you deploy the project in the local IIS, IIS will recognize the web.config file.
Assuming that there is no problem with your project, I think you can delete your web.config file first (must be backed up). Then use git to deploy, and then through kudu, find the web.config automatically generated by the deployment (also needs to be backed up, because subsequent operations will modify the source file, if the modification is wrong, you can restore it).
A post about git deployment to automatically generate web.config.
Compare the difference between the web.config content in your current project and the automatically generated git deployment, and add the functions and content you want, such as flushResponse="true",responseBufferLimit="0".
If something goes wrong, remember to restore the backup file. This can be used for troubleshooting.
I use azure app services for my nuxt application but when i use history.replaceState it doesnt replace the url. Running it on production on my own pc works fine but when I deploy it to azure it seems like its not doing anything. Maybe I did something wrong in my web.config?
(I also tried using this.$router.replace() which has the same results.)
selectBrand (brand) {
const errors = JSON.parse(JSON.stringify(this.error))
history.replaceState({}, null, window.origin + '/error/'+brand);
this.selectedBrand = brand
this.errorList = this.error.filter(name => name.cBrandname.includes(brand))
}
Here is my 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 https://azure.microsoft.com/en-us/blog/introduction-to-websockets-on-windows-azure-web-sites/ 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" 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\/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"/>
</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>
Thanks for raising the question and contributing to Stack Overflow.
Reiterating the answer from what Jason has mentioned as this should be solution for the problem you're facing .
Just create a sample Nuxt App and try to publish it again and see if it helps.
I am trying to run a simple node.js application on Azure cloud.
I basically followed the instruction written in the following websites.
-Creation of Web application-
https://code.visualstudio.com/tutorials/app-service-extension/create-app
-Deployment of Web application-
https://code.visualstudio.com/tutorials/app-service-extension/deploy-app
In order to run it on Azure(IIS), I added web.config and server.js in the root folder as below.
added 2 files
The contents of the files are as follows.
[web.config]
<configuration>
<system.webServer>
<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>
<!-- All URLs are mapped to the node.js site entry point -->
<rule name="DynamicContent">
<match url="/*" />
<action type="Rewrite" url="server.js"/>
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
[server.js]
The below shows only a part of the codes.
#!/usr/bin/env node
/**
* Module dependencies.
*/
var app = require('./app');
var debug = require('debug')('myexpressapp:server');
var http = require('http');
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
/**
* Create HTTP server.
*/
After deployed to Azure(IIS), the web application successfully ran. However, I would like to use the bin/www file instead of server.js. Actually, I created the server.js file in the root folder by coping the bin/www file.
In order to directly use bin/www, I changed the web.config as follows, but this leads to an error. The browser shows the error;"The resource you are looking for has been removed, had its name changed, or is temporarily unavailable." It seems that it cannot find the www file. Am I wrong with how I write the path?
<configuration>
<system.webServer>
<handlers>
<!-- Indicates that the server.js file is a node.js site to be handled by the iisnode module -->
<add name="iisnode" path="bin/www" verb="*" modules="iisnode"/>
</handlers>
<rewrite>
<rules>
<!-- All URLs are mapped to the node.js site entry point -->
<rule name="DynamicContent">
<match url="/*" />
<action type="Rewrite" url="bin/www"/>
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
I would appriciate any help.
I was able to solve the problem.
I changed the name of the folder from "bin" to some other name and it worked. I am trying to understand why the name "bin" does not work though...Is it because "bin" is kind of reserved by server and it can not be used? I would appriciate it if someone could let me know any possible reasons...
I've got an angular app that runs fine locally. I can run http-server and access the page. Now I am trying to move it to run in Azure. When I access the sitename.azurewebsites.net URL all I see is the actual text of my app.js file. Its not rendering as if it were on a nodejs server.
Here is the local directory structure. From the command line I cd to the app folder (app.js is in app\scripts folder) and use http-server to start it up. I see the angular app rendered as expected.
In Azure, I have web.config files that points to app/scripts/app.js file. When I access the sitename.azurewebsites.net URL, instead of the angular app running, I just get the app.js file served up to me as text. Like so:
Not sure what Azure setting is missing to let it know to run this as an Angular app. In the app Service I have an entry under Application Settings for Node:
WEBSITE_NODE_DEFAULT_VERSION 6.9.1
Here is the directory structure in Azure:
Here is the 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\scripts\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\scripts\^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\scripts\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" />
</system.webServer>
</configuration>
Well there were a few issues here but what I discovered :
the contents of the dist folder are all that was needed - I don't even have the web.config file anymore
the dist did not generate all files. The /scripts/vendor*.js file that was generated was empty. I fixed that by following suggestions here: Grunt build not populate scripts.js with bower_components
Updated the App Service-> Application Settings->Virtual applications and directories to point to site\wwwroot\dist - this probably isn't needed, I copied the dist folder instead of just it's contents. If I put the contents at the wwwroot level I probably would need this change.
I just deployed the code from github to azure.
It is a nodejs web app.
In azure, I'm using app services for this.
Also, I added the code for port in /bin/www
var port = process.env.port || 8080; // 8080 for local or whatever number u want
var listener = app.listen(port, function(){
console.log('Listening on port ' + port);
});
Still, webpage is not showing up in https://{appname}.azurewebsites.net
Here is the deployment log
Command: "D:\home\site\deployments\tools\deploy.cmd"
Handling node.js deployment.
KuduSync.NET from: 'D:\home\site\repository' to: 'D:\home\site\wwwroot'
Copying file: 'package.json'
Using start-up script bin/www from package.json.
Generated web.config.
The package.json file does not specify node.js engine version constraints.
The node.js application will run with the default node.js version 4.2.3.
Selected npm version 3.5.1
{github-reponame}#0.0.0 D:\home\site\wwwroot
├── lodash#4.4.0
└── underscore#1.7.0
Finished successfully.
For Justin Pattern's comment...
In scm, the structure of files, appear to be ok.
I did check the deployment log and the deployment is successful but the page is not displaying.
In scm kudu, the structure of the files appear to be ok. Still, only a blank page shows up when clicked on https://{appname}.azurewebsites.net
Hi Gary-Liu MSFT,
web.config is present in the root.
This is how the web.config looks like
<?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="bin/www" verb="*" modules="iisnode"/>
</handlers>
<rewrite>
<rules>
<!-- Do not interfere with requests for node-inspector debugging -->
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^bin/www\/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="bin/www"/>
</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>
Update:
July 24 - 11:05 p.m. EST -- looks like there is some clue to fix this... but now sure how..
Adding more info from the log file:
The log shows "No element in the source document matches... "
2016-07-25T03:03:26 Start 'websitelogs' site extension transform
2016-07-25T03:03:26 :(6,10), No element in the source document matches '/configuration/system.applicationHost/sites/site[#name='~1{appname}']/application[#path='/websitelogs']'
2016-07-25T03:03:26 Not executing Remove (transform line 6, 68)
2016-07-25T03:03:26 StartSection Executing Insert (transform line 7, 65)
2016-07-25T03:03:26 on /configuration/system.applicationHost/sites/site[#name='~1{appname}']/application
2016-07-25T03:03:26 Applying to 'site' element (no source line info)
Update Jul 25, 1:25 PM EST
For Gary-Liu MSFT's comment:
I tried commenting the "port" lines in github and redeployed it and it still azure shows only a blank page when accessed via https://{appname}.azurewebsites.net or http:{appname}.azurewebsites.net
From the application log...
2016-07-25T16:41:15 PID[15128] Warning The configured default provider 'MicrosoftAccount' was ignored
because it is not enabled. An alternate provider will be chosen arbitrarily.
2016-07-25T16:41:15 PID[15128] Information Sending response: 401.71 Unauthorized
the website still shows a blank page ....when accessed via http://{appname}.azurewebsites.net or https://{appname}.azurewebsites.net
the code was deployed via github repo. The website works fine without azure.
It just shows a blank page after deploying to azure web app...
Update:
July 25, 1:39pm EST
Thanks Gary-Liu MSFT
Resolved! Thanks!
Commenting the port lines helped! Thanks a lot! It is working now! Thanks!
In addition... It is because , in azure, for this web app, I had enabled the authentication/authorization to outlook acct. Switched it off and now no more blank page! The site works fine now! The reason , I enabled it to outlook acct was...i was hoping that it would prompt for outlook login! Thanks for your help! The site is up and running in azure now!
could you check whether you have a web.config file on the root directory of your application?
The content of the web.config should be similar with following:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
</appSettings>
<system.webServer>
<!-- mimeMap enables IIS to serve particular file types as specified by fileExtension. -->
<staticContent>
<mimeMap fileExtension=".svg" mimeType="image/svg+xml" />
</staticContent>
<modules runAllManagedModulesForAllRequests="false" />
<!-- Web.Debug.config adds attributes to this to enable remote debugging when publishing in Debug configuration. -->
<iisnode watchedFiles="web.config;*.js;routes\*.js;views\*.jade"/>
<!-- Remote debugging (Azure Website with git deploy): Comment out iisnode above, and uncomment iisnode below. -->
<!--<iisnode watchedFiles="web.config;*.js;routes\*.js;views\*.jade"
loggingEnabled="true"
devErrorsEnabled="true"
nodeProcessCommandLine="node.exe --debug"/>-->
<!-- indicates that the server.js file is a Node.js application
to be handled by the iisnode module -->
<handlers>
<add name="iisnode" path="/bin/www" verb="*" modules="iisnode" />
<!-- Remote debugging (Azure Website with git deploy): Uncomment NtvsDebugProxy handler below.
Additionally copy Microsoft.NodejsTools.WebRole to 'bin' from the Remote Debug Proxy folder.-->
<!--<add name="NtvsDebugProxy" path="ntvs-debug-proxy/ad81dc69-210e-42c6-80da-221ed1245211" verb="*" resourceType="Unspecified"
type="Microsoft.NodejsTools.Debugger.WebSocketProxy, Microsoft.NodejsTools.WebRole"/>-->
</handlers>
<security>
<requestFiltering>
<hiddenSegments>
<remove segment="bin" />
</hiddenSegments>
</requestFiltering>
</security>
<rewrite>
<rules>
<clear />
<!-- Remote debugging (Azure Website with git deploy): Uncomment the NtvsDebugProxy rule below. -->
<!--<rule name="NtvsDebugProxy" enabled="true" stopProcessing="true">
<match url="^ntvs-debug-proxy/.*"/>
</rule>-->
<rule name="app" enabled="true" patternSyntax="ECMAScript" stopProcessing="true">
<match url="iisnode.+" negate="true" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
<action type="Rewrite" url="bin\www" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
Any update or further concern, please feel free to let me know.
update
It seems there are a few mistakes on your repository code. It defines the port and make the http server to listen the port several times in your code. I did some modification , and deploy to Azure for testing, now it works fine on my side.
Please try to remove or comment following code snippet, and deploy to Azure again.
var listener = app.listen(port, function(){
console.log('Listening on port ' + port);
});
beginning at Line 18 of bin/www
var port = process.env.port || 8080; // 8080 for local or whatever number u want
var listener = app.listen(port, function(){
console.log('Listening on port ' + port);
});
beginning at Line 2 of app.js