We have a website hosted on DXP platform. None of the website is available anonymously - every vistor has to be logged.
Therfore the deployment takes ages, because it waits for timeout, and this things get logged:
Timed out waiting for all instances for webapp **************inte and slot "slot" to become ready!2020-09-10 09:43:23 ::PROGRESS:: PercentComplete=802020-09-10 09:43:23 Information Starting to warm up the targets slots...2020-09-10 09:43:50 Information Preparing target slot for Go Live (**************/slot) (warming up the slot)2020-09-10 09:55:11 Information Starting any continuous web job(s) in the slot if they exist (**************/slot)2020-09-10 09:55:13 Information Sending webrequests to validate the slot (**************/slot)...2020-09-10 09:55:47 Warning Site with URL http://**************-slot.dxcloud.episerver.net/ responded with error code: 403 (Forbidden)2020-09-10 09:55:47 ::DATA:: SiteName=**************;URL=http://**************-slot.dxcloud.episerver.net/;ManualValidationLink=http://integration.XYZ.com/?x-ms-routing-name=slot;StatusCode=403;StatusDescription=Forbidden2020-09-10 09:56:39 Information Warmup finished for all web apps!2020-09-10 09:56:39 Information Re-enabling autoscaling for the web apps in resource group **************2020-09-10 09:56:45 ::PROGRESS:: PercentComplete=90
So what I did, I created a simple API controller and action, which allows anonymous access, that loads start page through ContentLoader and direct children and returns list of loaded pages with status code OK 200.
Warmup controller looks like this:
public class WarmupController : ApiController
public IHttpActionResult Index()
// populate cache by retrieving start page and all direct child pages
var contentLoader = ServiceLocator.Current.GetInstance<IContentLoader>();
var pageSegments = new List<string>();
var startPage = contentLoader.Get<PageData>(ContentReference.StartPage);
if (startPage == null) return Ok<IEnumerable<string>>(pageSegments);
// load child pages
var childPages = contentLoader
.GetChildren<PageData>(startPage.PageLink).Where(x => x != null)
.Select(x => x.URLSegment);
I have added following initialization entry into transform file:
<!-- Application initialization -->
<applicationInitialization xdt:Transform="Remove" />
<add initializationPage="/api/warmup" hostName="integration.XYZ.com" xdt:Transform="InsertIfMissing" />
When accessing manually, https://integration.XYZ.com/api/warmup, I can confirm it's allowing anonymous access and it returns what it's supposed to. However from the logs, seems like it tries to hit the root of the page any ways, and it will always Forbidden because anonymous access is not allowed there due to bussiness requirements.
How to solve this issue? I bascially would like to shorten the warmup so that it doesn't take more than a half of the whole deployment time because of the forbidden URL. Ideally I would like the warmup to hit the endpoint I created for that reason.
Can you confirm that DXP is even calling your new API endpoint? You didn't mention it, and by default application initialization will hit the start page first (which gives the 403).
You could check that the web.config file has been correctly transformed with your additions.
Seems like it's not hitting that URL and it's indeed hitting start page, which deliberately is set to only allow authenticated traffic.
So now the question is: How could I authorize warmup requests to the page? OWIN middleware?
Then it does not sound like an authentication issue. More like a wrong configuration of the applicationInitialization configuration.
You could try connecting to the integration site with FTP and verify that the config transform you made is actually applied.
After further digging, I found out that it is calling my warmup URL (which takes about 4 seconds to complete), but yet it's still reporting timeout with the page URL which to me looks like it hits the start page anyway - even though it is not listed in applicationInitialization .
Application initialization looks like this, so it's properly transformed (from what I can tell):
<add initializationPage="/api/warmup" hostName="integration.XXX.com"/>
This might be tricky for you to solve, the deployment engine will currently always try to hit the start page of the domain when it tries to validate warmup. Warmup itself however should work as expected though (the deployment engine just tries to validate when/if this process has finished).
So to clarify: Application Initilization will go through the links you've added to the config (this is the actual warmup that also happens during scale outs). The deployment engine will ping the start page (it should follow redirects within the domain though) to try to monitor this (and check the header the app init process adds when it's running, which sadly is only returned if the response is 200 OK). If we can't validate that warmup has finished, we will ping the site until we hit our timeout value which seems to be the case here, it's not optimal but it's the safest way we can do this when we can't validate the warmup progress.
I don't have any good suggestions for how to workaround this problem currently (except for having a login page that responds with 200 OK, then this should be resolved). But we do have some planned work in this area ahead of us, so even though I can't make any promises on when/if this particular scenario will be fixed, I do have some hope of addressing this and will try to keep this scenario in mind when we do.
Small sidenote though is that even the fastest sites need a couple of minutes to warmup, initiate local cache and other internal processes in Azure etc., so we're really "just" talking about a few minutes of extra deployment time because of this, but I do of course get why you'd like this to be as quick as possible, and we do want to make this as fast as we possibly can as well.
Just saying that the entire time the deployment stays in this warmup validation phase isn't waste if that makes sense :-)