Vue.js served under IIS unable to find asset files - iis

UPDATE
After digging a bit further, I think the issue is related to the fact that referencing assets such as CSS files, e.g. href="/css/style.css" IIS will resolve it by navigating to the server's root folder, rather than application's root folder, e.g. localhost/myapp/css/style.css. However it seems to only occur when running Vue app, when I "deployed" raw html file in its own application, CSS and JS file paths were resolved correctly.
ORIGINAL POST
I have developed a sample to-do app in Vue.js with vue-router. When served using VUE CLI it works as expected, however when I built and put the files from dist folder under IIS application, I'm getting the errors which indicate that the server tries to find the asset files (such as css and js) at the localhost root, instead of localhost/todos. Example of errors:
http://localhost/css/app.45a2082d.css net::ERR_ABORTED 404 (Not Found)
http://localhost/js/app.34c2e8cc.js net::ERR_ABORTED 404 (Not Found)
I followed the steps for IIS specified here on the official website, i.e. installed IIS UrlRewrite and included the web.config, however I'm getting the same results. Included web.config:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Handle History Mode and custom 404/500" 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>
As a workaround, I tried creating a new ASP.Net core application. I put all the built asset files, including index.html under wwwroot folder and added the following middleware in the Startup.cs:
app.UseFileServer();
app.Run(async (context) => {
await context.Response.SendFileAsync(env.ContentRootPath + "/wwwroot/index.html");
});
This works as expected when launched through IIS Express, i.e. it loads the index.html file which in turn correctly loads all other assets. The routes are working correctly as I'm able to switch between the pages/routes (Home and About). However when I publish this web application and put it under IIS with the updated web.config file (the aforementioned URL rewrite rules + .Net Core specific configuration) I'm getting the same problem- the IIS seems to try loading assets from the root localhost locations.
How can I tell IIS to looks for the asset files at the root location of the application (i.e. iinetpub\wwwroot\Todos), and NOT at localhost's root?
My built dist files and directories look as follows:
index.html
css/app.45a2082d.css
js/app.34c2e8cc.js
vue-router configuration:
export default new Router({
mode: "history",
routes: [
{
path: "/",
name: "home",
component: Home
},
{
path: "/about",
name: "about",
component: About
}
]
});
Am I missing something else in the IIS config? Why would it work under IIS Express but not under system's IIS? Is the problem elsewhere?

It turned out that I had to configure Vue to set the baseUrl and match the application's path. In vue.config.js:
module.exports = {
baseUrl: '/todos'
};

Related

Azure web app giving HTTP error 500 when viewed, how can this be fixed?

trying to upload my mobile web application to azure
followed
https://learn.microsoft.com/en-us/azure/app-service/quickstart-nodejs?tabs=windows&pivots=development-environment-vscode
ended up just getting the error unable to handle request HTTP error 500
the web app works locally so i dont know what the issue is
a friend told me it was might be because all webpages in the views folder are .ejs files when they should be HTML.
I have followed the same document which you have provided and able to access the Application without any issues.
Create Node.js Application using the below command.
npx express-generator myExpApp19Dec --view ejs
Navigate to the Application root directory(myExpApp19Dec) and run npm install.
node_modules folder will be created at root of the directory.
Run npm start to start and run the application in local.
Open the Application from VSCode.
Steps to deploy Web App to Azure App Service
Sign into Azure => Click on Azure Icon => Select your Subscription = > App Services.
web app name - ExpressApp19Dec
runtime stack - Node 18 LTS
OS - Windows
Location - East US
Immediately after deployment, when I tried to access the Application, I got the below error.
Added SCM_DO_BUILD_DURING_DEPLOYMENT in Application Setting as suggested in the document.
Navigate to the deployed App folder in VSCode => Your App => Application Settings =>Add New Setting.
We can even add this Application Setting from Azure Portal => App Service => Configuration section. Re-deploy option can be excluded when we add Application Setting from Azure Portal.
Re-deploy the Application to get the latest changes.
Make sure web.config file is created at the root directory of the deployed Application in KUDU Console.
Path to KUDU Console -
https://YourAppServiceName.scm.azurewebsites.net/DebugConsole
My autogeneratedweb.config file
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<webSocket enabled="false" />
<handlers>
<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>
<rule name="StaticContent">
<action type="Rewrite" url="public{PATH_INFO}"/>
</rule>
<rule name="DynamicContent">
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
</conditions>
<action type="Rewrite" url="bin/www"/>
</rule>
</rules>
</rewrite>
<security>
<requestFiltering>
<hiddenSegments>
<remove segment="bin"/>
</hiddenSegments>
</requestFiltering>
</security>
<httpErrors existingResponse="PassThrough" />
</system.webServer>
</configuration>
Now Iam able to access the Application.
all webpages in the views folder are .ejs files when they should be HTML.
In VSCode => root folder => app.js file,
app.set('view engine', 'ejs');
This code helps to detect the ejs files. The issue is not with the ejs files.
EJS is an Embedded JavaScript template which is used by Node JS Application.

rewrite requests for always on bot in linux Azure app service

We are seeing some 404 logs coming from a bot in Azure always On. It trigged every 5min. Our health check is not in the root directory.
We are using Docker image for this, NodeJs 14.x. In documentation, they say to use web.config to redirect some urls but I'm not sure this will work.
<rule name="Redirect AlwaysOn requests from root to custom url" stopProcessing="true">
<match url="^$" />
<conditions>
<add input="{HTTP_USER_AGENT}" pattern="^AlwaysOn$" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/status" logRewrittenUrl="true" redirectType="Permanent"/>
</rule>
and not sure where to put this file in the container. Here's docker file
FROM node:15.0.1-alpine3.10
WORKDIR /usr/src/app
RUN mkdir node_modules
RUN mkdir dist
COPY node_modules node_modules
COPY dist dist
COPY apps/api/.docker/sshd_config /etc/ssh/
COPY apps/api/.docker/init.sh /usr/local/bin/
RUN chmod u+x /usr/local/bin/init.sh
ENTRYPOINT ["/usr/local/bin/init.sh"]
404 logs coming from a bot in Azure always On.
Issue can be fixed by rewriting the Always on path.
After a cold start of your application, AlwaysOn will send a request to the ROOT of your application “/”. Whatever file is delivered when a request is made to, / is the one which will be warmed up, it will fail because the root doesn’t exist.
Make AlwaysOn to warmup a specific page instead of the root, implement URL Rewrite rule.
<?xml version="1.0" encoding="UTF-8" standalone="no">
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Rewrite AlwaysOn" stopProcessing="true">
<match url="^$" />
<conditions>
<add input="{HTTP_USER_AGENT}" pattern="^AlwaysOn$" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/status" logRewrittenUrl="true" redirectType="Permanent"/>
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
web.config file needs to be added to the node app at the root
If your app has a server.js or app.js file in your Node.js project, the web.config file should be in the same directory.
If you are using Visual Studio Code , then Put web.config file in /public folder, It will then be copied over to /dist folder during build.
I have created the config file in public folder, After running npm run build , web.config file is copied to dist folder.
To create web.config, Right click on the public folder
Add new file, name it as web.config and add the above mentioned code snippet and save.
Go to Azure portal, your Web App =>Advanced Tools=>KUDU - Debug Console =>CMD => site=>wwwroot , check if web.config file exists or not.
If you are using Visual Studio, then select Azure Node.js Express template to craete the Web App, then web.config will be generated automatically.You can edit the settings directly.

Azure Webapp : What is the correct web.config in this case?

We are currently having some troubling in deploying a Node.js application on a Windows WebApp and we suspect that the problem is in the web.config file.
Here is Project Directory Structure:
We are using the default web.config with a few changes:
The application file is app.js and the public folder is dist/
<?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="dist{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>
Currently, the IIS Rewrite module is adding dist/ to the URL, like so: http://xxxxxxx.azurewebsites.net/dist/
And we have an iisnode error message:
HRESULT: 0x2
HTTP status: 500
HTTP subStatus: 1001
HTTP reason: Internal Server Error
I tried checking the Failed Request Tracing logs but no failed request was logged.
Could someone tell me what is happening in my case ?
EDIT:
I decided to start back from scratch and created a new Web app.
I built the node.js app with the kudu console and (using the same web.config) the server now fetches correctly the index.html file in dist/.
So far so good, and we correctly land on the login page.
The problem now is that iisnode fails to process the POST request with the user credentials.
As Julien suggested, I tried changing the virtual directory of the app and had different errors:
1st case:
Virtual directory: /
Path: site\wwwroot
Error: The same iisnode error as the above
2nd case:
Virtual directory: /
Path: site\wwwroot\dist
Error: The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
Any thoughts on that ?
Thank you
Actually, your web.config is correct.
You can try replacing the content of app.js with the following minimal Node.js app to see if it works.
var http = require('http');
var server = http.createServer(function(req, res) {
res.writeHead(200);
res.end('Hello Azure');
});
server.listen(process.env.PORT);
Important: use process.env.PORT as the port in your script when it runs on Azure Web Service.
Depending on how you are pushing your App to web app, you can try to:
Use the PROJECT environment variable to specify that your app is in the dist folder, as explained here.
Define a virtual directory in the web app settings to specify that the root folder of your application is site\wwwroot\dist. You can find a JSON example of configuration here or use the Application Settings blade in the Azure portal.
Hope this helps
Julien

host node js on windows server (iis)

I started learning server side coding a month ago, I build a nodejs project and webservices with get and post requests using 'express' framework and mssql.
My project file includes a 'main.js' file and a 'node_modules' folder.
I'm trying to host this project on IIS but have no idea or experience on how to do so.
Will i have to package my project in some way.
Can i host nodejs projects on IIS? If so, then what are the steps that I need to do so.
I have a windows server running IIS with mysql installed there.
Here is a step by step...
if you havent done so install node, iisnode and urlrewrite
add a website to iis
edit the hosts file
add your website url to host
check your new website modules to ensure iisnode is installed
If its there you're good
create the node app code JS file
Put this code in the file
var express = require("express");
var app = express();
app.get("/", function(req, res) {
res.send("Hello Worlxxxxd!");
});
// This is REQUIRED for IISNODE to work
app.listen(process.env.PORT, () => {
console.log("listening");
});
add a web.config file to the directory and put this code in it
<configuration>
<system.webServer>
<handlers>
<add name="iisnode" path="node_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="/node_app.js" />
</rule>
</rules>
</rewrite>
<security>
<requestFiltering>
<hiddenSegments>
<add segment="node_modules" />
<add segment="iisnode" />
</hiddenSegments>
</requestFiltering>
</security>
</system.webServer>
</configuration>
in a browser navigate to the new site and you should get this error because you haven't installed express package
open a command prompt and install express
refresh the web page and voila
I'm a little late to the party, so you've probably either solved this problem or gone a different route.
You can run node applications inside of IIS using iisnode.
I, personally, have had mixed success getting iisnode running, but it is definitely possible.
I'd recommend using the URL Rewriting (https://www.iis.net/downloads/microsoft/url-rewrite) and Application Request Routing (https://www.iis.net/downloads/microsoft/application-request-routing) IIS modules. Install these on your server hosting IIS.
In IIS create an application that points to the directory where your node application is running (although this path is not actually used!):
In this new application, create a Rewrite Rule using the Reverse Proxy template, and point to your locally served node js application:
And now, you can browse to your IIS hosted site, using the IIS application you had configured, and it will show your node.js hosted site:
One of the main benefits of this approach is that the SSL cert issued to IIS can be used with an "http" hosted node.js application.
I've got node.js running from the command line, but this could be done as a service if needed.

Need to fix routing issue with Angular 2 running on an Azure App service

I have an angular 2 website that is based on the Angular 2 "Tour of Heroes" Quick Start.
It works fine when running locally. After fixing things to no longer use local node_modules (per the deployment steps from the quick start) and deploying to the Azure web app the app works fine if I start at the root URL ("/"). However, using Angular routing the URL changes (to "/home" for example) and if I do an F5 refresh of that URL, the app fails to load. When I do that I get a 404 with:
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
I tried using a web.config as described here but that did not help. It definitely seems like it is an IIS issue where it tries to serve up a page instead of starting with index.html. My routes are defined in Angular and they work locally.
Can you try this 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>
<caching enabled="true" enableKernelCache="true">
<profiles>
<add extension=".js" policy="DisableCache" kernelCachePolicy="DisableCache" />
</profiles>
</caching>
</system.webServer>
</configuration>
The web.config solution did not work for me at all. After a day or so of digging around and tearing my hair out, I came across this post which resolved the issue for me. It appears to be doing something similar in that for a 404 that isn't related to any /api/ request, serve up the root page, whereupon the Angular routing should kick in and serve up the correct view. As per the link above, in Startup.cs at the beginning of the void Configure() method, I inserted the following code:
app.Use(async (HttpContext context, Func<Task> next) =>
{
await next.Invoke();
if (context.Response.StatusCode == 404 && !context.Request.Path.Value.Contains("/api"))
{
context.Request.Path = new PathString("/");
await next.Invoke();
}
});
The only thing I've done differently is set the root url to '/' (my root razor page that's hosting the Angular app) instead of index.html in the example. The versions I'm using are .NET Core 2.2 and Angular 7.2.1.
Add this file in src/assets/routes.json
{
"routes": [
{
"route": "/*",
"serve": "/index.html",
"statusCode": 200
}
]
}
let me know if it workes ?
Not sure if it's too late, but here is what you need
app-routing.module.ts add useHash: true
modify your navigation to use #
compile your application: ng build --configuration production
upload your files to your static site

Resources