Nuxt 3 app on IIS not serving static files - iis

I'm trying to deploy a Nuxt 3 app on a server using IIS.
The idea is to use reverse proxy to rewrite requests from the external https://www.example.com to the internal http://localhost:8080 where the app is running.
It should be straight forward I thought, with an inbound rule matching everything (.*) and a Rewrite URL like http://localhost:8080/{R:1}:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="ReverseProxyInboundRule1" stopProcessing="true">
<match url="(.*)" />
<action type="Rewrite" url="http://localhost:8080/{R:1}" logRewrittenUrl="true" />
</rule>
</rules>
</rewrite>
<httpErrors existingResponse="PassThrough" />
</system.webServer>
</configuration>
But apparently only the dynamic routes are being served correctly, all public static files are not. On those this is the curl response: curl: (92) HTTP/2 stream 0 was not closed cleanly: CANCEL (err 8).
Other notes:
Opening the app locally on http://localhost:8080 works perfectly.
The same behaviour occurs with a fresh Nuxt app.
Usage of iisnode seems not possible because of ES Modules incompatibility: iisnode Error [ERR_REQUIRE_ESM]: require() of ES Module (...)index.mjs not supported.

After adding a rule to force HTTPS it started working as expected, all static files are being served as expected.
<rule name="Force HTTPS" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="^OFF$" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" appendQueryString="false" />
</rule>

Related

IIS Rewrite / Application Request Routing (ARR) Half-working

I have several rules in my rewrite, including ARR that have been working for over a year, now it's almost like the top rules in the web.config file are no longer being called in the correct order.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="AuthRoute" stopProcessing="true">
<match url="(auth$|auth/(.*))" />
<action type="Rewrite" url="http://localhost:8083/auth/{R:2}" />
</rule>
...
<rule name="Non-File Routes" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
</conditions>
<action type="Rewrite" url="/index.html" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
As you can see, I have a separate route for /auth that reverse-proxies to a different application designed for everything in /auth ... In this case, there are several files foo.HASH.css and foo.HASH.js that are actually there, the backend application is serving them, but the front end is getting the parent application (via IIS) of the /index.html.
Some files are being reverse proxied correctly, others simply are not. It's weird, I'm not sure if it's a windows/iis update that started this or what.
Turns out the content for the app being reverse proxied wasn't being published with the path prefix. Since browsers aren't showing the full path in the list, the aren't too load from root was missed.

IIS Rewrite Module and sub applications / React-Router

Ok, this is similar to other questions out there but I am not familiar with url rewrite.
I am hosting (hopefully only for development and testing) a react application under IIS.
If hosted in the root of the site folder all is well using
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Static Assets" stopProcessing="true">
<match url="([\S]+[.](svg|js|css|png|gif|jpg|jpeg))" />
<action type="Rewrite" url="{R:1}" />
</rule>
<rule name="ReactRouter 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>
But I need it to work in a subapplication. For instance: http://myserver:8888/myapp. Where myapp is the sub application.
IIS diagram:
Sites
- MySite
- MyApp
Better example of the url that includes the route: http://myserver:8888/myapp/1234/abcd.
1234 and abcd are route values/params.
contents of my app directory are:
index.html
main.a9e1df0325f4fdb57e7e.js
vendors~main.c8848853e10f698af19d.js
web.config
Thanks
Gina
You could host your app in any subapplication in iis but be careful to defining correct route for serving contents. It seems you want to host static content so you can't use route parameters in url hence these parameters are used by asp.net. Static content are served by iis. You can try this url for serving content in myapp:
http://myserver:8888/myapp/index.html

Reverse proxy for backend apps with IIS 8, ARR and URL rewrite on 1 server

Situation is that I have 2 backend apps and I need to set up HTTPS access for them. I install IIS 8 with ARR and URL rewrite module on the server. Than I install 2 https certificates and create an empty website with binding on 443 port
with second app https certificate. First app is set upped on 8081 ports and second app on port 80. The problem is that I can access via https only to first app and second app could be accessed via http only. So I am trying to set up reverse proxy, so I could access to the second app via https. I wrote 2 inbound rules in URL rewrite, but I got issue when I try to access to second app it is pointing not to localhost:80 but it pointing to localhost:8081. any suggestions why it happen?
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<clear />
<rule name="App2" stopProcessing="true">
<match url="^app2/(.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
<action type="Rewrite" url="http://localhost:80/{R:1}" />
</rule>
<rule name="Redirection" stopProcessing="true">
<match url="^app2/(.*)" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{SERVER_PORT}" pattern="443" />
</conditions>
<action type="Redirect" url="https://app2/{R:0}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>

IIS URL Rewrite ~ Rewriting Paths to Ports

My situation is as follows:
We have an array of CI services, such as TeamCity, YouTrack and OctopusDeploy on a single server. Currently, we are accessing all of these via DNS Name plus port, e.g.:
TeamCity: http://server.company.com
YouTrack: http://server.company.com:1234
OctopusDeploy: http://server.company.com:5678/octopus
I'm currently adjusting that so we can access these services via https. For that purpose, I've set up an IIS Server as a Reverse Proxy by using IIS URL Rewrite to handle SSL authentication. This already works, and I can now access TeamCity via https://server.company.com
However, while I'm at it, I would also like to use IIS URL Rewrite to beautify the addresses, and get rid of the need to memorize port numbers. What I want to achieve are the following redirects:
https://server.company.com -> http://server.company.com (already working)
https://server.company.com/youtrack -> http://server.company.com:1234
https://server.company.com/octopus -> http://server.company.com:5678/octopus
I have already tried adding the following rules:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<clear />
<rule name="ReverseProxyInboundRule2" stopProcessing="true">
<match url="^(https://server.company.com/youtrack)(.*)$" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
<action type="Rewrite" url="http://server.company.com:1234/{R:2}" />
</rule>
<rule name="ReverseProxyInboundRule1" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAny" trackAllCaptures="false">
<add input="{PATH}" pattern="youtrack" negate="true" />
</conditions>
<action type="Rewrite" url="http://server.company.com/{R:1}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
...and tested it in the IIS Manager, which correctly recognizes the rules and conditions, and also returns the correct backwards rules.
However, when I try to access https://server.company.com/youtrack, I am redirected to http://server.company.com/youtrack instead of http://server.company.com:1234 as I intended. It's like the ReverseProxyInboundRule2 is not evaluated at all.
I'm sure there's a logical explanation for this and a way to make it work. I just can't see it on my own. What can I do to make this work?
UPDATE 30-Mar-2018:
Okay, so I figured out a configuration that partially works. It goes as follows:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<clear />
<rule name="Reverse Proxy to TeamCity" stopProcessing="true">
<match url="^teamcity/(.*)" />
<action type="Rewrite" url="http://server.company.com/{R:1}" />
</rule>
<rule name="Reverse Proxy to YouTrack" stopProcessing="true">
<match url="^youtrack/(.*)" />
<action type="Rewrite" url="http://server.company.com:1234/issues/{R:1}" />
</rule>
<rule name="Reverse Proxy to Hub" stopProcessing="true">
<match url="^hub/(.*)" />
<action type="Rewrite" url="http://server.company.com.de:5678/hub/{R:1}" />
</rule>
<rule name="Reverse Proxy to UpSource" stopProcessing="true">
<match url="^upsource/(.*)" />
<action type="Rewrite" url="http://server.company.com.de:9876/{R:1}" />
</rule>
<rule name="Reverse Proxy to Octopus" stopProcessing="true">
<match url="^octopus/(.*)" />
<action type="Rewrite" url="http://server.company.com:5432/octopus/{R:1}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
This configuration redirects the requests as follows:
https://server.company.com -> http://server.company.com
https://server.company.com/youtrack -> http://server.company.com:1234/issues/
https://server.company.com/hub -> http://server.company.com:5678/hub/
https://server.company.com/upsource -> http://server.company.com:9876
https://server.company.com/octopus -> http://server.company.com:5432/octopus/
This works perfectly for Octopus.
On Hub, there is a "Connection is not secure" notification next to the address, saying that "Parts of the web site (such as images) are not secure". Going into the page info, it says in the Security tab under Technical Details that the Connection is only Partially Encrypted. However, the rest of the page appears to be working fine.
TeamCity and YouTrack are more whimsical. On Chrome, TeamCity works fine (for a while until it gets a random disconnect) but YouTrack delivers a 404 error, while on Firefox both TeamCity and YouTrack are displayed in an unusable "text-only" form.
UpSource, meanwhile, delivers a blank page on either browser.
I've cross-tested this on various browsers and machines and came to the conclusion that TeamCity, YouTrack and Hub only "sort of" work if I am already logged into the http versions of those services on those servers. If I am not logged in, then I get 404 errors for TeamCity and YouTrack. As for Hub, I get a 405 error on trying to log in with a "POST-Method not supported" message.
So the basic result of my above written configuration on a clean slate is as follows:
TeamCity: 404 Error
YouTrack: 404 Error
Hub: 405 Error on login
UpSource: Blank Page
Octopus: Working
Okay, after a lot of back and forth, I figured out a working configuration for all of these services:
Set up a http IIS Reverse proxy
The following modules need to be installed in IIS:
URL Rewrite (via https://www.iis.net/downloads/microsoft/url-rewrite)
Application Request Routing (via https://www.iis.net/downloads/microsoft/application-request-routing)
WebSocket Protocol (va Server Manager: Web Server (IIS) > Web Server > Application Development > WebSocket Protocol)
Dynamic Content Compression (via Server Manager: Web Server (IIS) > Web Server > Performance > Dynamic Content Compression)
Create a website for the URL redirect
Create a https binding for that website using a valid certificate
Disable Dynamic Content Compression under [Server] > Compression
Go to [Server] > Application Request Routing > Server Proxy Settings and select ☑ “Enable Proxy”
Make sure the following values are set:
HTTP Version: Pass Through
Time-out: 120
Preserve client Ip for the following header: X-Forwarded-For
Memory Cache Duration: 60
Query String Support: Ignore Query String
Response Buffer: 4096
Response Buffer Threshold: 0
Set up the URL rewrite and related settings
Add the following server variables in [Server] > URL Rewrite > View Server Variables
HTTP_X_FORWARDED_HOST
HTTP_X_FORWARDED_SCHEMA
HTTP_X_FORWARDED_PROTO
Configure the web.config as follows:
web.config:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<clear />
<rule name="Reverse Proxy to TeamCity" stopProcessing="true">
<match url="^teamcity(.*)" />
<action type="Rewrite" url="http://server.company.com{R:1}" />
</rule>
<rule name="Reverse Proxy to Hub" stopProcessing="true">
<match url="^hub(.*)" />
<action type="Rewrite" url="http://server.company.com:8082/hub{R:1}" />
<serverVariables>
<set name="HTTP_X_FORWARDED_HOST" value="{HTTP_HOST}" />
<set name="HTTP_X_FORWARDED_SCHEMA" value="https" />
<set name="HTTP_X_FORWARDED_PROTO" value="https" />
</serverVariables>
</rule>
<rule name="Reverse Proxy to YouTrack" stopProcessing="true">
<match url="^youtrack(.*)" />
<action type="Rewrite" url="http://server.company.com:8080/youtrack{R:1}" />
<serverVariables>
<set name="HTTP_X_FORWARDED_HOST" value="{HTTP_HOST}" />
<set name="HTTP_X_FORWARDED_SCHEMA" value="https" />
<set name="HTTP_X_FORWARDED_PROTO" value="https" />
</serverVariables>
</rule>
<rule name="Reverse Proxy to UpSource" stopProcessing="true">
<match url="^upsource(.*)" />
<action type="Rewrite" url="http://server.company.com:8081/upsource{R:1}" />
<serverVariables>
<set name="HTTP_X_FORWARDED_HOST" value="{HTTP_HOST}" />
<set name="HTTP_X_FORWARDED_SCHEMA" value="https" />
<set name="HTTP_X_FORWARDED_PROTO" value="https" />
</serverVariables>
</rule>
<rule name="Reverse Proxy to Octopus" stopProcessing="true">
<match url="^octopus(.*)" />
<action type="Rewrite" url="http://server.company.com:8888/octopus{R:1}" />
</rule>
<rule name="Reverse Proxy to Collaboration General" stopProcessing="true">
<match url="(.*)" />
<action type="Rewrite" url="http://server.company.com/{R:1}" />
</rule>
</rules>
</rewrite>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="300000000" maxUrl="6144" maxQueryString="4096" />
</requestFiltering>
</security>
</system.webServer>
</configuration>
Configure Hub, YouTrack and UpSource as follows
NOTE: The commands beginning with hub.bat / youtrack.bat / upsource.bat need to be performed on the respective file in [Installation Directory]\bin of the respective service.
cmd:
upsource.bat stop
youtrack.bat stop
hub.bat stop
hub.bat configure --listen-port 8082 --base-url https://server.company.com/hub
youtrack.bat configure --listen-port 8080 --base-url=https://server.company.com/youtrack--hub-url=https://server.company.com/hub/hub
upsource.bat configure --listen-port 8081 --base-url=https://server.company.com/upsource --hub-url=https://server.company.com/hub/hub
hub.bat start
youtrack.bat start
upsource.bat start --J-Dbundle.websocket.compression.enabled=false
NOTE: I don't know why, but Hub appends an extra /hub after its base address, that's why the hub-url setting for UpSource ends with /hub/hub.
After that, all I needed to do was add the redirection URLs to the list of allowed redirection URLs for the services and change the basis urls for TeamCity and OctopusDeploy in Hub > Settings > Services, and now it all works perfectly.
Well, almost perfectly. Whenever the server gets restarted I need to manually restart UpSource since I've not yet figured out a way to register upsource as a service with the --J-Dbundle.websocket.compression.enabled=false parameter, but apart from that, everything works perfectly.

Azure web app redirect http to https

I use Azure cloud with web app and my server side written on nodejs.
When web app receive a http request I want to redirect the request to https
I found the solution.
I put that to my web.config file inside the rules tag
<rule name="Force HTTPS" enabled="true">
<match url="(.*)" ignoreCase="false" />
<conditions>
<add input="{HTTPS}" pattern="off" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" appendQueryString="false" redirectType="Permanent" />
</rule>
The problem is when I type in the browser "https://myURL.com" it redirect to main screen every thing ok,
but when I change https to http "http://myURL.com" it redirect to https://myURL.com/" and add to the url "bin/www" according that the url looks like that "http://myURL.com/bin/www", the response is: page doesn't find.
The question is how to redirect a clear url without added data to the url?
Part of my web.config file:
<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>
<!-- Redirect all traffic to SSL -->
<rule name="Force HTTPS" enabled="true">
<match url="(.*)" ignoreCase="false" />
<conditions>
<add input="{HTTPS}" pattern="off" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" appendQueryString="false" redirectType="Permanent" />
</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>
Thanks for answers, Michael.
Go to Azure portal and open the overview page of the (Web) App Service you wanna set to HTTPS only. In the sidebar, under the Settings section, there is an option for TLS/SSL Settings.
On clicking it, you will get an option on the screen to set your app's protocol to HTTPS only. There isn't any need to manually add separate ruleset for this.
This works on every tier of App Service Plan including the 'F'-Series (free subscription).
Note that, if you are adding any custom domain you also need to add corresponding SSL bindings, you can easily get them using LetsEncrypt or alike. If any of the custom hostnames for your app are missing SSL bindings, then:
When HTTPS Only is enabled clients accessing your app on those custom hostnames will see security warnings.
PS: I just saw that this question was asked about 3 years ago and that time maybe there was no direct option to do this. But even so, I'm posting my answer because on Google (as on February 2020) this question still ranks first among others regd. automatic HTTPS redirection in Azure.
As of November 2017, this is now a simple switch in the Azure Portal: "HTTPS Only", under Custom domains.
https://blogs.msdn.microsoft.com/benjaminperkins/2017/11/30/how-to-make-an-azure-app-service-https-only/
It's also very easy in ARM:
“httpsOnly”: true
There is also a free and open source extension for this.
Go to your Web App settings sidebar, search for the "Extensions" tab and click on "Add".
Scroll down and find the extension Redirect HTTP to HTTPS by gregjhogan.
Accept the terms.
Restart the Web App for the actions to take effect immediately.
Done !
For further details on the implementation of this extension, check the source code on GitHub. The most important source file is the applicationhost.xdt.
Quote from GitHub (02-08-2017) (credits go to gregjhogan):
applicationhost.xdt
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<location path="%XDT_SITENAME%" xdt:Transform="InsertIfMissing" xdt:Locator="Match(path)">
<system.webServer xdt:Transform="InsertIfMissing">
<rewrite xdt:Transform="InsertIfMissing">
<rules xdt:Transform="InsertIfMissing" lockElements="clear">
<rule name="redirect HTTP to HTTPS" enabled="true" stopProcessing="true" lockItem="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
<add input="{WARMUP_REQUEST}" pattern="1" negate="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" appendQueryString="true" redirectType="Permanent" />
</rule>
</rules>
</rewrite>
</system.webServer>
</location>
</configuration>
R:1 is a back-reference to the rule pattern. You append that to the url here:
url="https://{HTTP_HOST}/{R:1}"
changing that into
url="https://{HTTP_HOST}"
should result in a redirect to the https root.

Resources