This is the third time in the last year that I’ve had to setup a HTTP 301 redirect in Azure for a customer. Doing so improves the general quality of life experience for users accessing various Microsoft 365 services, like for example specific SharePoint Online team sites, or Exchange Online OWA.
With each implementation I turned to Azure App Service to deliver the functionality needed. The first time I created an App Service Web App and used the web.config file method, described in further detail in this blog post, to achieve that. The second time I had to do that, I simply copied the first process and got things up and running as quickly and easily as the first time. The third time, which was very recent, I decided to use Azure Functions to do that via an App Service Functions app instead.
Users (don’t forget that you’re one of them) want things to be efficient, reliable, and often times as easy as possible to get something done. Improving that quality of life user experience wins you (the administrator or architect of systems and services) brownie points and frees up time to do more important things than having to listen to those pesky users again.
The main example I’m going to use in this blog is around SharePoint Online and providing a streamlined way to access a specific team site that a department might have put together to outline a series of new initiatives or policies within your enterprise. SharePoint Online can have some length URI’s for those team site pages buried within the navigation tree in department X and business unit Y and so on. You’ll end up with something that looks like:
Who on earth is going to remember that URI to be able to communicate that to users effectively? Sure, bookmarks work great and so does CTRL+C and CTRL+V. In reality, it’s not a pretty URI to look at, to remember or distribute. So, with the use of some Azure App Service, some HTTP 301, we can condense this down to something that users can remember:
I guarantee that no one in the enterprise will forget that URL! (Oh, and in case you were wondering, that URL does not work; it’s just an example)
This is nice and easy and quick to do. It’s a very reliable method of 301 redirect as well with even the lowest App Service Plan which for me seems like the right plan for this given that its very light work.
To execute this process, here’s all you need to do:
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Redirect" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTP_HOST}" pattern="^important.lucian.franghiu.com$" />
</conditions>
<action type="Redirect" url="https://AwesomeCustomer.Sharepoint.com/Sites/DepartmentThatRunsTheShow/WhereAmI/WhatIsThisCoolThing/OhThereItIs/Important/SitePages/Home.aspx" redirectType="Permanent" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
I said earlier that this is a quick process, and in practice there isn’t too many difficult steps, but it can be a bit long to complete. In addition, having an App Service sitting there waiting, essentially running “warm” regardless if anyone hits the site to be redirected seems like it’s wasting compute and money.
When the third request for a redirect came in, I thought it would be great idea to reduce some of that consumption spend, reduce some of the wasted and idle compute and embrace serverless!
The following process is how you would achieve the same HTTP 301 redirect, but using some C# code running as an Azure Function app in the App Service stack:
using static System.Environment;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net;
using Microsoft.Extensions.Logging;
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, ILogger log)
{
string OriginUrl = req.Headers.GetValues("DISGUISED-HOST").FirstOrDefault();
log.LogInformation("RequestURI org: " + OriginUrl);
//create response
var response = req.CreateResponse(HttpStatusCode.MovedPermanently);
if((OriginUrl.Contains("Desired FQDN like imporant.lucian.franghiu.com")) || (OriginUrl.Contains("Azure Web App FQDN like example.azurewebsites.net")))
{ response.Headers.Location = new Uri("Target FQDN like https://lucian.franghiu.com/aboutlucian"); }
else
{ return req.CreateResponse(HttpStatusCode.InternalServerError); }
return response;
}
After implementation and testing, the redirect via Azure Function App Service worked well. I tried a number of times in a short span of time across different web browsers on my Surface Pro 6. All looked great.
However, this was all within the range of the Azure Functions idle window of 20 minutes. From what I understand, once a Function is “warm”, it will remain idle in this state for about 20min to execute follow up requests in a nice snappy manner. After that idle period expires though, the warmth dissipates, and we’re left with some cold Function.
This cold state of Function is a deal breaker for using this particular solution for me and this third redirect request. For my customers use case, there’s not enough user volume over a 24-hour period to keep the Function App, under the Consumption service plan, to maintain the warm state, even with a total user count exceeding 35,000 Microsoft 365 licensed users.
To best describe this, I’d encourage you to check the following blog posts from Azure MVP Mikhail Shilkov, @MikhailShilkov:
In the testing I conducted with cold starts, he redirect Function took 18.37sec to run. I could imagine that this would likely happen quite often for this particular redirect I wanted to setup. I know that not every employee of the customer would be hitting the URL all that often. I also didn’t want to switch back to a non-Consumption Service Plan as I wanted to really embrace and take advantage of serverless.
…I went with the original solution via the web.config file method because the cold start limitation. This original method is fast, is still relatively cheap to run and even cheaper to maintain (nothing needs to be done!). I’ll come back to this in the future when there’s improvements in Functions cold start. For now, if it isn’t broken, don’t fix it.