Add Azure CDN (or any CDN) to your Episerver site

Frederik Vig 2017-12-30 14:19:28

We'll be using Azure CDN for this, but any CDN can be used. The site doesn't have to be hosted in Azure either. If you have a multi site Episerver solution, the setup is a bit different with one CDN endpoint per site, this is to support loading assets from different sites, since the CDN acts as a proxy between the request and the server. By default Azure will cache the resources for 7 days, you can override this and setup your own rules.

Step 1: Creating a CDN profile

Login to the Azure portal and go to the CDN profile service. Here we can create a new profile that we'll use in this tutorial. 

When it comes to the pricing tier, it will depend on you're requirements, we'll pick Standard Verizon.

Step 2: Adding an endpoint

After creating the profile we can now create an endpoint.

For origin type we'll select the Custom origin option. This will allow us to add the domain name of the site, which all uncached requests will be forwarded to.

This will ensure that www.example.com/images/logo.png and example.azureedge.net/images/logi.png both work.

Note: It might take up to 8 hours for the endpoint to be properly created, so be patient.

Step 3: Configuring HTTP Headers

Since the CDN just will act as a proxy and use the HTTP Headers from the Episerver site, you need to make sure that this is configured.

Fiddler is a great tool for checking HTTP Headers.

Here's some more background information and examples: CDN recommendations.

Step 4: Add URL rewrite rules

In web.config we need to add the rewrite rules to change the URLs to CDN URLs at runtime.

<rewrite>
<outboundRules rewriteBeforeCache="true">
<!-- Site specific assets -->
<rule name="CDN-site1-img" preCondition="CheckHTML" stopProcessing="false">
<match filterByTags="Img" pattern="(^(?!www\.|(?:http|ftp)s?:\/\/|[A-Za-z]:\\|\/\/).*\.(jpg|jpeg|png|gif).*)" />
<conditions logicalGrouping="MatchAll">
<add input="{URL}" pattern="^\/?episerver\/CMS" negate="true" />
<add input="{HTTP_HOST}" pattern="site1.com" />
</conditions>
<action type="Rewrite" value="https://site1.azureedge.net{R:1}" />
</rule>

<rule name="CDN-site2-img" preCondition="CheckHTML" stopProcessing="false">
<match filterByTags="Img" pattern="(^(?!www\.|(?:http|ftp)s?:\/\/|[A-Za-z]:\\|\/\/).*\.(jpg|jpeg|png|gif).*)" />
<conditions logicalGrouping="MatchAll">
<add input="{URL}" pattern="^\/?episerver\/CMS" negate="true" />
<add input="{HTTP_HOST}" pattern="site2.com" />
</conditions>
<action type="Rewrite" value="https://site2.azureedge.net{R:1}" />
</rule>
<!-- End site specific assets -->

<rule name="CDN-01-js" preCondition="CheckHTML" stopProcessing="false">
<match filterByTags="Script" pattern="(^(?!www\.|(?:http|ftp)s?:\/\/|[A-Za-z]:\\|\/\/).*\.(js).*)" />
<action type="Rewrite" value="https://example.azureedge.net{R:1}" />
<conditions>
<add input="{URL}" pattern="^\/?episerver" negate="true" />
</conditions>
</rule>
<rule name="CDN-01-css" preCondition="CheckHTML" stopProcessing="false">
<match filterByTags="Link" pattern="(^(?!www\.|(?:http|ftp)s?:\/\/|[A-Za-z]:\\|\/\/).*\.(css).*)" />
<action type="Rewrite" value="https://example.azureedge.net{R:1}" />
<conditions>
<add input="{URL}" pattern="^\/?episerver" negate="true" />
</conditions>
</rule>
<rule name="CDN-01-icons" preCondition="CheckHTML" stopProcessing="false">
<match filterByTags="Link" pattern="(^(?!www\.|(?:http|ftp)s?:\/\/|[A-Za-z]:\\|\/\/).*\.(jpg|jpeg|png|gif|ico).*)" />
<action type="Rewrite" value="https://example.azureedge.net{R:1}" />
<conditions>
<add input="{URL}" pattern="^\/?episerver" negate="true" />
</conditions>
</rule>
<preConditions>
<preCondition name="CheckHTML">
<add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
</preCondition>
</preConditions>
</outboundRules>
</rewrite>

The negate pattern is to not rewrite the URLs when in edit mode. Thanks to my colleague Māris Krivtežs for all of this.

Step 6: Testing and debugging

Webpagetest can be run to see how CDN support looks. If you're having problems with HTTP Headers, remember that all CDNs offer a way to Purge resources (either individual or all), together with Fiddler, should allow you to debug most problems.