Cannot warm up pages using applicationInitialization in webconfig - azure

I have a simple Umbraco 7.7.2 application and I'm hosting it on Azure (app-service). When I restart the server it takes 20-40 seconds for first time requesting a page which is really annoying specially when the load is high and you are Scaling out to reduce the response times.
I've tried this setting in my webconnfig, but it doesn't seem to work.
<system.webServer>
<applicationInitialization>
<add initializationPage="/page1/?warmup=1" hostName="mydomain.com" />
<add initializationPage="/page1/page2/?warmup=1" hostName="mydomain.com" />
</applicationInitialization>
</system.webServer>
I might be trying it in a wrong way, but what I did was to restart the server and I've left it for 2-3 minutes without requesting any page.
I've checked my Umbraco logs and the application wasn't even started.
Then I've requested the home page and it took 40 seconds to come up.
Then I've tried mydomain.com/page1 and it also took 20 seconds since it was the first request to access it.
*P.S: after the first request, the site is very fast and each page takes less than 100 ms to load
Update
I've implemented a rewrite to stop next redirects as Kevin has suggested.
As a result, my Umbraco will start up, but still the requests doesn't reach to the pages.
On my master page, I've added a line to write a line in the logs if it has the warmup in the querystring and it works it the page is hitted from the browser:
if (!string.IsNullOrWhiteSpace( Request.QueryString["warmup"]))
{
var pageC = Model.Content;
logger.Info(pageC.UrlAbsolute()+" "+ Request.QueryString);
}
However, there is nothing in my logs after
2018-02-08 15:16:51,245 [P7036/D2/T1] INFO Umbraco.Core.CoreBootManager - Umbraco application startup complete (took 12727ms)
2018-02-08 15:16:54,911 [P7036/D2/T1] INFO MyNamespace.Web.CustomStartup - base config done!
Here is the confing that I've added based on Kevin's answer:
<rule name="No redirect on warmup request (request from localhost with warmup user agent)" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{REMOTE_ADDR}" pattern="127.0.0.*" />
</conditions>
<action type="Rewrite" url="{URL}" />
</rule>
Also, I've found another similar config on Microsoft:
<rule name="No redirect on warmup request (request from localhost with warmup user agent)" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTP_HOST}" pattern="localhost" />
<add input="{HTTP_USER_AGENT}" pattern="Initialization" />
</conditions>
<action type="Rewrite" url="{URL}" />
</rule>

Note that azure will warm up the URL on http, so if you are forcing https using rewrite rules, the full site will not warm up, only the redirect module will. Then it needs to finish warming up Umbraco after azure adds it into the load balancer and the first https gets through to the umbraco code. We found that out by checking the http logs when scaling out.
We couldn't figure out how to tell azure to warmup using https, so we allowed Azure to access the site on http by making a rule before our force https rewrite to stopProcessing when {REMOTE_ADDR} matches 127.0.0.*.
<rule name="Allow localhost to warmup" stopProcessing="true">
<match url="(.*)"/>
<conditions>
<add input="{REMOTE_ADDR}" pattern="127.0.0.*" />
</conditions>
</rule>

There was so many reasons for the requests not reaching my site and thanks to Kevin and Twamley whom opened my eyes to the probable cause I could trace and find all of them.
First, as Kevin said HTTPS was one of the issues which I've fixed as below:
<rule name="No redirect on warmup request (request from localhost with warmup user agent)" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTP_HOST}" pattern="localhost" />
<add input="{HTTP_USER_AGENT}" pattern="Initialization" />
</conditions>
<action type="Rewrite" url="{URL}" />
</rule>
Then I could see that Umbraco starts up but the requests didn't get to my pages.
<rule name="Redirect rquests to www.example.com" stopProcessing="true" enabled="true">
<match url="(.*)" />
<conditions >
<add input="{HTTP_HOST}" pattern="^example\.com$" />
</conditions>
<action type="Redirect" url="https://www.example.com/{R:0}" />
</rule>
I didn't expect my requests to get to this redirect since it was at the end of my rewrite rules and therefore it should be stoped at No redirect on warmup request but it didn't so I've added another condition to it: <add input="{HTTP_USER_AGENT}" pattern="Initialization" negate="true" />
<rule name="Redirect rquests to www.example.com" stopProcessing="true" enabled="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAll">
<add input="{HTTP_HOST}" pattern="^example\.com$" />
<add input="{HTTP_USER_AGENT}" pattern="Initialization" negate="true" />
</conditions>
<action type="Redirect" url="https://www.example.com/{R:0}" />
</rule>
Also, I have ipSecurity in my settings since it is my test environment and I didn't want it open to public. Turns out the Initialization cannot hit my site at all if I don't open up to 127.0.0.1.....
<security>
<ipSecurity allowUnlisted="false">
<add ipAddress="127.0.0.1" allowed="true" />
<add ipAddress="x.x.x.x" allowed="true" />

I like Kevin's idea of just stopping the processing as one of the first rewrite rules. I noticed his didn't have an action but you added one to yours. Maybe try his w/o an action? Is it the first rule in the file?
Another option we use is to add this condition to any problem rules (notice the negate).
<add input="{REMOTE_ADDR}" pattern="127\.0\.0\.1" negate="true"/>
Try temporarily clearing your rewrite rules until you're convinced your warmup is working, then add the rules back a few at a time to find and fix the problem redirect. Force SSL and Trailing Slash type rules will definitely cause problems.
Also, the hostName can get you in trouble easily. It should be a perfect match for your production environment. It doesn't use DNS to resolve it, it just talks to the local site and passes that in as the HOST header.
I don't have any querystrings in my warmup list. Maybe you should try dropping those. You don't really need them because you can change your logging code to:
if (Request.IsLocal && Request.UserAgent == "IIS Application Initialization Warmup") {
// log it
}
Logging them is a great idea because the warm up requests don't show up in the standard IIS logs. I have my servers mail me at the beginning and end of the warmup by hitting a special first and last entry that uses that if statement. Some useful details from Azure:
new {
WEBSITE_HOSTNAME = System.Environment.GetEnvironmentVariable("WEBSITE_HOSTNAME"),
WEBSITE_INSTANCE_ID = System.Environment.GetEnvironmentVariable("WEBSITE_INSTANCE_ID"),
WEBSITE_SITE_NAME = System.Environment.GetEnvironmentVariable("WEBSITE_SITE_NAME"),
COMPUTERNAME = System.Environment.GetEnvironmentVariable("COMPUTERNAME"),
USER_AGENT = Request.UserAgent,
URL = Request.Url,
WARM_UP_TIME = (DateTime.UtcNow - _start).ToString()
}

Related

Domain Redirect from domain.com/pathA to domainA.com

I have an IIS web server that is setup to handle all requests to *.myapp.com. We also have clients that have setup a custom domain, e.g. custom.customer.com as a CNAME To customer.myapp.com
I have a requirement to handle the following:
Requests to custom.customer.com/pathA will need to be redirected to a.internal-app.com
Requests to custom.customer.com/pathB will need to be redirected to b.internal-app.com
The problem I have right now is that this can't be done on the DNS level (as it involves paths). Also, whatever the "redirect" is I want the client to see his custom domain at all times. Like he should never see internal-app.com or myapp.com.
Is this possible in any way?
It is possible with reverse proxy.
1) You need to install URL Rewrite and ARR module for IIS
2) Enable ARR. On the Application Request Routing page, select Enable proxy
3) Create rewrite rule
<rewrite>
<rules>
<rule name="rewrite custom.customer.com/patha" stopProcessing="true">
<match url="patha" />
<conditions logicalGrouping="MatchAll">
<add input="{HTTP_HOST}" pattern="^custom.customer.com$" ignoreCase="true" />
</conditions>
<action type="Rewrite" url="http://a.internal-app.com/" />
</rule>
<rule name="rewrite custom.customer.com/pathB" stopProcessing="true">
<match url="pathb" />
<conditions logicalGrouping="MatchAll">
<add input="{HTTP_HOST}" pattern="^custom.customer.com$" ignoreCase="true" />
</conditions>
<action type="Rewrite" url="http://b.internal-app.com/" />
</rule>
</rules>
</rewrite>
P.S. You might have problem with your resources(images,styles,css,js). Because your html might contains absolute paths to resources
You can check this post, when author is creating outbound rule for fixing relative urls https://blogs.iis.net/carlosag/setting-up-a-reverse-proxy-using-iis-url-rewrite-and-arr

Do I need anything besides code written in web.config to redirect website hosted on azure to https

I have a website that I host on azure. I recently bought an SSL and configured it. Now users can visit my site by typing in either http://example.com or https://example.com.
What I want is for users who type in the former to be automatically redirected to the latter while also keeping anything after the .com
So if a user types in http://example.com/about they will be redirected instead to https://example.com/about.
After some reading, I've come across this code that seems to do what I want
<system.webServer>
<rewrite>
<rules>
<rule name=”Redirect to https”>
<match url=”(.*)”/>
<conditions>
<add input=”{HTTPS}” pattern=”Off”/>
<add input=”{REQUEST_METHOD}” pattern=”^get$|^head$” />
</conditions>
<action type=”Redirect” url=”https://{HTTP_HOST}/{R:1}”/>
</rule>
</rules>
</rewrite>
</system.webServer>
But before I add this to my web.config file I have a few questions.
What is the IIS url rewrite module? IIS Rewrite and is it required to be installed on my azure hosted websites before I upload my new web.config file.
How can I also include removing www from my URL when a user enters it. For example if a user types in www.example.com they should be redirected to https://example.com instead. The reason that I want this is because in my google search console I've told google to display URLs as example.com rather then www.example.com
and finally, will this code do what I'm looking for? Is there a more professional way to achieve this? What are the benefits. I should note that my sites are asp .net web forms. I know MVC has routing options but that is not an option for me.
Edit : I don't think How to force HTTPS using a web.config file solves my issue because I don't even know if I can install the URL Rewrite module since I am not hosting IIS myself. Does azure give you access to the IIS settings? I am unfamiliar with azure details.
The Microsoft URL Rewrite Module for IIS enables IIS administrators to create powerful customized rules to map request URLs to friendly URLs that are easier for users to remember and easier for search engines to find.
This module is pre-installed for Azure Web App, as shown when inspect the applicationHost.config of the Azure Web App in Kudu.
Hence, you do not need to worry about the availability of the module for Azure Web App.
The URL Rewrite configuration to enforce HTTPS redirection for Azure web app is the simplest way to achieve what you intend. Your above configuration will apply
only if the request method is either HTTP GET or HTTP HEAD. The below configuration will not have such limitation.
<system.webServer>
<rewrite>
<rules>
<rule name="Force HTTPS Redirection" enabled="true" stopProcessing="true">
<match url="^$" ignoreCase="false"/>
<conditions>
<add input="{HTTPS}" pattern="^OFF$"/>
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/" redirectType="Permanent"/>
</rule>
</rules>
</rewrite>
</system.webServer>
I would add one last thing. Assuming you are running on Azure Web Apps, they have various probes to your site for warm up and initialization. You probably don't want these probes to also be redirected, otherwise, you may have some issues when you restart or use Azure's swaps feature for stuff like blue/green deployments. These probes would then be return with a 301/302 rather than actually hitting your site (and Azure doesn't actually follow the redirect)
More examples https://github.com/projectkudu/kudu/wiki/Xdt-transform-samples
<rule name="Redirect to non-WWW" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTP_HOST}" pattern="www.example.com$" />
<add input="{HTTP_USER_AGENT}" pattern="Initialization" negate="true" /> <!-- IIS Application Initialization Warmup -->
<add input="{HTTP_USER_AGENT}" pattern="SiteWarmup" negate="true" /> <!-- Azure WebApps Warmup Request -->
<add input="{HTTP_USER_AGENT}" pattern="AlwaysOn" negate="true" /> <!-- Azure WebApps AlwaysOn Probes -->
</conditions>
<action type="Redirect" redirectType="Permanent" url="https://example.com/{R:1}" />
</rule>
<!-- Redirect to HTTPS Version -->
<rule name="HTTP to HTTPS redirect" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
<add input="{HTTP_USER_AGENT}" pattern="Initialization" negate="true" />
<add input="{HTTP_USER_AGENT}" pattern="SiteWarmup" negate="true" />
<add input="{HTTP_USER_AGENT}" pattern="AlwaysOn" negate="true" />
</conditions>
<action type="Redirect" redirectType="Permanent" url="https://{HTTP_HOST}/{R:1}" />
</rule>

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.

Redirect *azurewebsites.net to .com but not for CDN

I have a Joomla site on Azure. I have set up the .com properly and I understand why the *azurewebsites.net URL is still working.
I wanted to redirect all traffic from *azurewebsites.net to the .com. I followed this guide and it works as intended.
http://onthecloud.azurewebsites.net/seo-tip-how-to-block-the-.azurewebsites.net-domain
However, I also have an Azure CDN in place (mycdn.azureedge.net/). I use JCH Optimize to set up the CDN. I see the the calls to mycdn.azureedge.net/ are generated properly. However, somehow, because of the web.config redirect, all the traffic is redirected from the CDN back to my .com, which defeats the purpose of the CDN. This creates a lot of redirect calls.
Is there a way to write the web.config lines to exclude the CDN?
Here's what my web.config looks like. When I delete those lines, the CDN redirects disappear, so the problem is really here.
<rule name="Disable Azure Domain" patternSyntax="Wildcard" stopProcessing="true">
<match url="*" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{HTTP_HOST}" pattern="*.azurewebsites.net" />
</conditions>
<action type="Redirect" url="http://www.example.com{REQUEST_URI}" redirectType="Permanent" />
</rule>
Look at your conditions. You're filtering all traffic that goes to "*.azurewebsites.net". All calls to your cdn fall into that filter as well, which is why you're seeing them be redirected:
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{HTTP_HOST}" pattern="*.azurewebsites.net" />
</conditions>
Instead, filter the calls just to your website. So your condition would look more like:
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{HTTP_HOST}" pattern="yoursite.azurewebsites.net" />
</conditions>
That'll let calls to the CDN go through just fine.
You can find more details on setting up redirect rules for your Azure Web App here: http://zainrizvi.io/2016/04/07/block-default-azure-websites-domain/
Fyi, below is the full web.config that I use for my site. You'll not that I've set some of the other settings a bit differently. Try using that web.config file instead (just change the site names as appropriate) and see if it works for you.
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Redirect to zainriziv.io" stopProcessing="true">
<match url="(.*)" />
<conditions logicalGrouping="MatchAny">
<add input="{HTTP_HOST}" pattern="^zainrizvi\.azurewebsites\.net$" />
</conditions>
<action type="Redirect" url="http://www.zainrizvi.io/{R:0}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
Note: When you're testing the fix your browser might have cached the redirect, so you might want to try fiddler or a new browser/pc to verify things work as expected

IIS UrlRewrite problem

I've been using the UrlRewrite IIS plugin for about a month on our production site.
I created a single redirect rule using the supplied template/wizard, the resulting config enrty is as follows:
<rewrite>
<rules>
<rule name="CanonicalHostNameRule1" enabled="true">
<match url="(.*)" />
<conditions>
<add input="{HTTP_HOST}" pattern="^www\.mycompany\.com$" negate="true" />
</conditions>
<action type="Redirect" url="http://www.mycompany.com/{R:1}" />
</rule>
</rules>
</rewrite>
It's been running fine until this morning, when the site started erroring with "too many redirects". As far as I know, nothing in the configuration or infrastructure changed.
I disabled the rule, and the site became functional again (though clearly without any redirecting).
I then re-enabled the rule, and now all is running as expected. I didn't make any changes to the rule other than to temporarily disable it.
Any ideas? Is the plugin buggy?
I'd recommend setting this up:
http://learn.iis.net/page.aspx/467/using-failed-request-tracing-to-trace-rewrite-rules/
This may help you track down the problem if you start getting the "too many directs" error again.
Try this other code, i have on my web and run perfect:
<rule name="Canonical Host Name" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTP_HOST}" pattern="^yourdomain\.com$" />
</conditions>
<action type="Redirect" url="http://www.yourdomain.com/{R:0}" redirectType="Permanent" />
</rule>
The explanation is simple:
Match any URL received to process
The condition is that have anydomaintext.extension (your domain and extension) without prefix
Redirect to same domain with full prefix and put all url.
Other tries was R:1 but quit some of the main url and not run.
The sample from Ruslani:
http://blogs.iis.net/ruslany/archive/2009/04/08/10-url-rewriting-tips-and-tricks.aspx
I tried to use adding www but finally use the sample above.
The fix below worked for me. I discovered my rewrite rule was at out-of-date. The other domain had changed their URL policy and were now redirecting all traffic from otherdomain.com to www.otherdomain.com
<action type="Rewrite" url="http://otherdomain.com/abc/{R:1}" />
to
<action type="Rewrite" url="http://www.otherdomain.com/abc/{R:1}" />
Do you see the difference? By adding the 'www' I preempted the other domain redirection. I basically just complied with their new policy.

Resources