diff --git a/src/Our.Umbraco.AzureCDNToolkit/AzureCdnToolkit.cs b/src/Our.Umbraco.AzureCDNToolkit/AzureCdnToolkit.cs
index 9cdf34c..f90a23e 100644
--- a/src/Our.Umbraco.AzureCDNToolkit/AzureCdnToolkit.cs
+++ b/src/Our.Umbraco.AzureCDNToolkit/AzureCdnToolkit.cs
@@ -60,6 +60,13 @@ public static AzureCdnToolkit Instance
///
public string MediaContainer { get; set; }
+ ///
+ /// The timeout in milliseconds used when connecting to the cdn
+ /// The default value for the is 100 seconds
+ /// so this is specified as the default value here
+ ///
+ public int CdnConnectionTimeout { get; set; } = 100 * 1000;
+
///
/// Sets all properties
///
@@ -68,7 +75,6 @@ public static AzureCdnToolkit Instance
public void Refresh()
{
-
if ((WebConfigurationManager.AppSettings["AzureCDNToolkit:UseAzureCdnToolkit"] != null))
{
var useAzureCdnToolkit = bool.Parse(WebConfigurationManager.AppSettings["AzureCDNToolkit:UseAzureCdnToolkit"]);
@@ -84,6 +90,15 @@ public void Refresh()
this.CdnUrl = WebConfigurationManager.AppSettings["AzureCDNToolkit:CdnUrl"];
this.AssetsContainer = WebConfigurationManager.AppSettings["AzureCDNToolkit:AssetsContainer"] ?? "assets";
this.MediaContainer = WebConfigurationManager.AppSettings["AzureCDNToolkit:MediaContainer"] ?? "media";
+
+ if (!string.IsNullOrWhiteSpace(WebConfigurationManager.AppSettings["AzureCDNToolkit:CdnConnectionTimeout"]))
+ {
+ int cdnConnectionTimeout = 0;
+ if (int.TryParse(WebConfigurationManager.AppSettings["AzureCDNToolkit:CdnConnectionTimeout"], out cdnConnectionTimeout))
+ {
+ CdnConnectionTimeout = cdnConnectionTimeout;
+ }
+ }
}
}
diff --git a/src/Our.Umbraco.AzureCDNToolkit/Events/UmbracoEvents.cs b/src/Our.Umbraco.AzureCDNToolkit/Events/UmbracoEvents.cs
index cebca26..c16e94d 100644
--- a/src/Our.Umbraco.AzureCDNToolkit/Events/UmbracoEvents.cs
+++ b/src/Our.Umbraco.AzureCDNToolkit/Events/UmbracoEvents.cs
@@ -25,7 +25,12 @@ protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplica
private void ImageProcessingModule_ValidatingRequest(object sender, ImageProcessor.Web.Helpers.ValidatingRequestEventArgs args)
{
var securityToken = WebConfigurationManager.AppSettings["AzureCDNToolkit:SecurityToken"];
- var securityModeEnabled = bool.Parse(WebConfigurationManager.AppSettings["AzureCDNToolkit:SecurityModeEnabled"]);
+ var securityModeEnabled = false;
+
+ if (!bool.TryParse(WebConfigurationManager.AppSettings["AzureCDNToolkit:SecurityModeEnabled"], out securityModeEnabled))
+ {
+ securityModeEnabled = false;
+ }
if (securityModeEnabled && !string.IsNullOrWhiteSpace(args.QueryString) && !string.IsNullOrEmpty(securityToken))
{
diff --git a/src/Our.Umbraco.AzureCDNToolkit/UrlHelperRenderExtensions.cs b/src/Our.Umbraco.AzureCDNToolkit/UrlHelperRenderExtensions.cs
index c387f0a..36f26d4 100644
--- a/src/Our.Umbraco.AzureCDNToolkit/UrlHelperRenderExtensions.cs
+++ b/src/Our.Umbraco.AzureCDNToolkit/UrlHelperRenderExtensions.cs
@@ -82,7 +82,7 @@ public static IHtmlString GetCropCdnUrl(this UrlHelper urlHelper,
public static IHtmlString ResolveCdn(this UrlHelper urlHelper, string path, bool asset = true, bool htmlEncode = true)
{
- return ResolveCdn(urlHelper, path, AzureCdnToolkit.Instance.CdnPackageVersion, asset, htmlEncode:htmlEncode);
+ return ResolveCdn(urlHelper, path, AzureCdnToolkit.Instance.CdnPackageVersion, asset, htmlEncode: htmlEncode);
}
// Special version of the method with fallback image for TinyMce converter
@@ -166,7 +166,7 @@ public static IHtmlString ResolveCdn(this UrlHelper urlHelper, string path, stri
if (asset && !path.InvariantContains("/media/"))
{
- cdnPath = string.Format("{0}/{1}", AzureCdnToolkit.Instance.CdnUrl, AzureCdnToolkit.Instance.AssetsContainer);
+ cdnPath = string.Format("{0}/{1}", AzureCdnToolkit.Instance.CdnUrl, AzureCdnToolkit.Instance.AssetsContainer);
}
else
{
@@ -228,9 +228,12 @@ internal static IHtmlString UrlToCdnUrl(string cropUrl, bool htmlEncode, string
// If toolkit disabled return orginal string
if (!AzureCdnToolkit.Instance.UseAzureCdnToolkit)
{
+ LogHelper.Info(typeof(UrlHelperRenderExtensions), "AzureCdnToolkit is disabled");
return new HtmlString(cropUrl);
}
+ LogHelper.Info(typeof(UrlHelperRenderExtensions), "AzureCdnToolkit is enabled");
+
if (string.IsNullOrEmpty(currentDomain))
{
currentDomain = HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority);
@@ -260,28 +263,61 @@ internal static IHtmlString UrlToCdnUrl(string cropUrl, bool htmlEncode, string
absoluteCropPath = string.Format("{0}&securitytoken={1}", absoluteCropPath, securityToken);
}
- // Retry five times before giving up to account for networking issues
- TryFiveTimes(() =>
+ // lazy load the image
+ Lazy LazyLoadCdnImage = new Lazy(() =>
{
- var request = (HttpWebRequest)WebRequest.Create(absoluteCropPath);
- request.Method = "HEAD";
- using (var response = (HttpWebResponse)request.GetResponse())
+ string result = null;
+
+ try
{
- var responseCode = response.StatusCode;
- if (responseCode.Equals(HttpStatusCode.OK))
+
+ // parse the image through the handler directly
+
+ // HttpContext.Current
+
+
+
+ // Retry five times before giving up to account for networking issues
+ TryFiveTimes(() =>
{
- var absoluteUri = response.ResponseUri.AbsoluteUri;
- newCachedImage.CacheUrl = absoluteUri;
+ var request = (HttpWebRequest)WebRequest.Create(absoluteCropPath);
+ request.Timeout = AzureCdnToolkit.Instance.CdnConnectionTimeout;
+ request.Method = "HEAD";
+ using (var response = (HttpWebResponse)request.GetResponse())
+ {
+ var responseCode = response.StatusCode;
+ if (responseCode.Equals(HttpStatusCode.OK))
+ {
+ result = response.ResponseUri.AbsoluteUri;
+ }
+ }
+ });
+ }
+ catch(Exception ex)
+ {
+ LogHelper.Error(typeof(UrlHelperRenderExtensions), "Error resolving media url from the CDN", ex);
- // this is to mark URLs returned direct to Blob by ImageProcessor as not fully resolved
- newCachedImage.Resolved = absoluteUri.InvariantContains(AzureCdnToolkit.Instance.CdnUrl);
+ // we have tried 5 times and failed so let's cache the normal address
+ newCachedImage = new CachedImage { WebUrl = cropUrl };
+ newCachedImage.Resolved = false;
+ newCachedImage.CacheUrl = cropUrl;
+ Cache.InsertCacheItem(cacheKey, () => newCachedImage);
- Cache.InsertCacheItem(cacheKey, () => newCachedImage);
- fullUrlPath = response.ResponseUri.AbsoluteUri;
- }
+ result = cropUrl;
}
- });
+ newCachedImage.CacheUrl = result;
+ // this is to mark URLs returned direct to Blob by ImageProcessor as not fully resolved
+ newCachedImage.Resolved = fullUrlPath.InvariantContains(AzureCdnToolkit.Instance.CdnUrl);
+ Cache.InsertCacheItem(cacheKey, () => newCachedImage);
+
+ return result;
+
+ },
+ System.Threading.LazyThreadSafetyMode.PublicationOnly);
+
+
+ fullUrlPath = LazyLoadCdnImage.Value;
}
else
{