Deploy on azure continous delivery custom node app - node.js

I have a node app that has both a react native front end and a node API
I want to be able to just run npm install for both folders and then just have it run the start command "node server" (node/server/index.js) to have the node app running.
But I can't seem to figure out the release tasks to make this happen.
I am using the preview continous delivery that connects to visual studio online

In my opinion, it has nothing to do with continuous delivery. Since Azure App Service runs on Microsoft IIS, you'll need to have an IIS configuration file named web.config and should include the following section to match your requirement:
<handlers>
<add name="iisnode" path="./node/server/index.js" verb="*" modules="iisnode"/>
</handlers>
This indicates that the node/server/index.js file is a node.js site to be handled by the iisnode module.
<rewrite>
<rules>
<!-- 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="./node/server/index.js"/>
</rule>
</rules>
</rewrite>
These rewrite rules determine where your static content and dynamic content should be located in.
For a completed web.config file you can check this post out.

Related

404 File or directory not found with query subpath

IIS 10 is throwing the error
404 File or directory not found
Only when I try to access the url with subfolder path like this:
http://myserveraddress.com/object/181
So it works without the subfolder. The subfolder path is used by Angular to query a rest interface so there is no physical folder path behind it, just used for querying behind the schene.
This actually works when running on localhost but not on the server.
Is it possible to configure IIS such that it allows any url path even though the physical folder path does not exist?
This loos more like a handler configuration issue, and also if your server is a brand new server may be you haven't installed the handlers which is supposed to process your request, if i have to take a request if you haven't configured the rest handlers required it is goind to the static file handler which tries to look for a folder in the request url path and throw an error, if you already have a setup running, check all the handlers and pre-requisites installed there and mimic the setting over in the new server as well
The solution was to add this to the Angular client web.config file
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="AngularJS 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="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
More detail can be found here Get Angular2 routing working on IIS 7.5

NodeJS at Azure : systematic 404 error on resource files

we have a nodeJS webapp at Azure which works fine.
When streaming the server logs, any time I load a page, I get a bunch of 404 errors on all resources (images, css, etc..). Yet the page shows up properly.
Detailed errors show the following:
Requested URL https://[myappname]:80/settings.png
Physical Path D:\home\site\wwwroot\settings.png
Logon Method Anonymous
Logon User Anonymous
The requested URL is clearly wrong, it should be https://[myappname].azurewebsites.net/settings.png, which is the public URL for the given resources, and works fine.
This problem loads huge amounts of logs and makes it impossible to use Web Server logs for now.
thank you!
Edit: unlike this problem, my pages load properly and the resource files are well available.
Solved I have added the following handler to my web.config :
<add name="UrlRoutingModule-4.0" path="*" verb="*" type="System.Web.Routing.UrlRoutingModule" preCondition="" />
I believe you need to configure a ruleset in your web.config for static file content.
<rule name="StaticContent">
<action type="Rewrite" url="public{REQUEST_URI}"/>
</rule>
Node.js applications running on Azure Web Apps are hosted on IIS via IISNode. So, a web.config file is required to config your application on IIS. If you deploy your app to Azure App Service via Continuous Deployment, the web.config file will be automatically generated by Azure. Or you can download the file from here.
I am posting default web.config just for your reference"
<?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 app.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
To debug your node.js application:
* set the debuggingEnabled option to "true"
* enable web sockets from the portal at https://manage.windowsazure.com/#Workspaces/WebsiteExtension/Website/aarontestnode/configure
* browse to https://aarontestnode.azurewebsites.net/app.js/debug/
See https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config for a full list of options
-->
<iisnode watchedFiles="web.config;*.js" debuggingEnabled="false" />
</system.webServer>
</configuration>
Hope it helps.
thanks for your answer.
I have nearly the same web.config, automatically generated. There is just a slight difference in the rule you pointed :
<rule name="StaticContent">
<action type="Rewrite" url="public{PATH_INFO}"/>
</rule>
My server code includes this:
app.use(express.static(path.join(__dirname, 'public')));

Node.js Route not working on Microsoft Azure

Hello I build a very basic Node.js app (without any framework),
I set up a route.
index.html and login.html
on my local machine (windows 10) its working fine. both files index.html and login.html show up in browser when I call them from url. like
localhost/myapp => loads index.html
localhost/myapp/login => loads login.html
Now I deploy it on Microsoft Azure, and now only index file is loading, when i try to load myapp.azurewebsites.net/login it said this : The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
I have a web.config file with these settings
<?xml version="1.0"?>
<configuration>
<system.webServer>
<staticContent>
<mimeMap fileExtension=".html" mimeType="text/html" />
</staticContent>
</system.webServer>
</configuration>
please guide me how to enable routing in node.js on azure. without any framework. there is no help on official docs.
thanks
well after a lot of search I figure out the solution.
you need to set web.config file from their demo project and upload into your own azure project.
https://github.com/Azure-Samples/nodejs-docs-hello-world/archive/master.zip
You could use the Azure Node JS Starter Site or Node JS Empty Web App.
In those projects you will find the right web.config file that you need to run Node applications in Azure.
Try to add below code in web.config file and see if it works.
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Main Rule" 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>
</system.webServer>
</configuration>
For more details on this error follow this link.

Sails looking in wrong directory

I'm new to sails.js and node.js, so the question might be trivial, but I couldn't find the answer. I have deployed my node.js app to a web site in IIS, so the app can be reached at http://example.com/myapp/. When browsing to http://myhost.com/myapp/app.js, I get http status 404 (Not found), because sail.jss is looking for URLs like http://myhost.com/images/logo.png, but this file is in fact located at http://myhost.com/myapp/.tmp/public/images/logo.png. This .tmp folder seems to be created on the fly by the framework.
Can someone shed some light on this?
[edit]
I have added rewrite rules in the web.config and it works much better. But it only works if I put the application at the root of my web site (acessing http://myhost.com/). If I put the application in a lower level (accessing through http://myhost.com/myApp), then the added rules do not seem to produce any effect.
Here is the web.config:
<handlers>
<add name="iisnode" path="app.js" verb="*" modules="iisnode" />
</handlers>
<rewrite>
<rules>
<rule name="StaticContent">
<action type="Rewrite" url="assets{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>
The key is to allow Express to handle all of the routing. The best way to do that is to route all traffic to app.js via iisnode (from: https://nodestream.wordpress.com/2015/11/24/sails-js-configuration-for-iis/):
<configuration>
<system.webServer>
<!-- Tell IIS to use the iisnode module to run your
application -->
<handlers>
<add name="iisnode" path="app.js" verb="*" modules="iisnode" />
</handlers>
<!-- Add iisnode with the #nodeProcessCommand line if
you see the error: Make sure the node.exe executable
is available at the location specified in the
system.webServer/iisnode/#nodeProcessCommandLine element
of web.config. -->
<iisnode
nodeProcessCommandLine="%ProgramFiles%\nodejs\node.exe"
/>
<!-- Since behind the covers, Sails.js is just an express app
rewrite all urls to processed by iisnode via app.js. This
will sort out things like the routing to your public
resources (images, js, styles) and all configured rest
endpoints. -->
<rewrite>
<rules>
<rule name="root">
<match url=".*" />
<action type="Rewrite" url="app.js" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
Well the .tmp folder is created by Grunt. You can reference the gruntfile and the task folder. The pipeline.js allows you to select files/folders for grunt to inject and spit out. You can easily change this to point to /images and /js folders.
tasks/pipline.js
module.exports.cssFilesToInject = cssFilesToInject.map(function(path) {
return '.tmp/public/' + path; // Change this
});
module.exports.jsFilesToInject = jsFilesToInject.map(function(path) {
return '.tmp/public/' + path; // Change this
});
Another solution I could think of, however I am not sure if IIS has it, is to do a rewrite rule. When a user goes to site.com/images, point them to .tmp/public/images. It is common to see that in Apache servers.

Deploying Express 4.x app to Windows Azure

The new version of Express separates the modules from the "server" file. It now lives in /bin/www and I'd prefer to keep this convention if possible.
In the package.json file, the "start" script clearly points to the right place, but this is seemingly ignored by Azure.
How do I deploy an Express 4.x app without having a server.js file in the root directory? All I need to do is make it automatically call node ./bin/www instead of node server.js. Is there another root configuration file I can add specific to the cloud host (Azure?) This is how I got this working in Heroku, etc.
updated answer
The Azure team has since fixed this internally. A newly deployed express 4 app should work just fine on Azure Websites without any additional changes.
original answer
I'll start with the tl;dr. Create a web.config file in the root of your application and use this xml.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<!--
By default IIS will block requests going to the bin directory for security reasons.
We need to disable this since that's where Express has put the application entry point.
-->
<security>
<requestFiltering>
<hiddenSegments>
<remove segment="bin" />
</hiddenSegments>
</requestFiltering>
</security>
<handlers>
<!-- Indicates that the www file is a node.js entry point -->
<add name="iisnode" path="/bin/www" verb="*" modules="iisnode"/>
</handlers>
<rewrite>
<rules>
<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.
This means IIS will handle your static resources, and you don't have to use express.static
-->
<rule name="StaticContent">
<action type="Rewrite" url="public{REQUEST_URI}"/>
</rule>
<!-- All other URLs are mapped to the node.js entry point -->
<rule name="DynamicContent">
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
</conditions>
<action type="Rewrite" url="/bin/www"/>
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
This is a bit of a mess and took a while to track down. I really wish it was smart enough to look at package.json, but this is what we have to deal with for now. Normally Azure determine if it is a Node application by checking for an app.js or server.js file. If it finds that file, it will automatically create a web.config file very similar to what is above. In this case, it will detect app.js, but unlike 99% of other node applications, that's not actually the entry point. What we have to do is change the entry point to /bin/www like shown above.
The other issue we run into is that by default IIS blocks requests to the bin folder for security reasons. We can either rename the express bin folder, or tell IIS to get over it. That's what the hiddenSegments part of the xml file is for.

Resources