public async Task Invoke(HttpContext context) { var path = context.Request.Path; // Delegate to the diagnostics page if it is requested if (diagnosticsPage.MatchesPath(path.Value)) { await diagnosticsPage.Invoke(context); return; } // We only handle requests with an image extension, period. if (!PathHelpers.IsImagePath(path)) { await next.Invoke(context); return; } var imageJobInfo = new ImageJobInfo(context, options, blobProvider); if (!imageJobInfo.Authorized) { await NotAuthorized(context); return; } // If the file is definitely missing hand to the next middleware // Remote providers will fail late rather than make 2 requests if (!imageJobInfo.PrimaryBlobMayExist()) { await next.Invoke(context); return; } var memoryCacheEnabled = memoryCache != null && options.AllowMemoryCaching && imageJobInfo.NeedsCaching(); var diskCacheEnabled = diskCache != null && options.AllowDiskCaching && imageJobInfo.NeedsCaching(); var distributedCacheEnabled = distributedCache != null && options.AllowDistributedCaching && imageJobInfo.NeedsCaching(); var sqliteCacheEnabled = sqliteCache != null && options.AllowSqliteCaching && imageJobInfo.NeedsCaching(); string cacheKey = null; if (memoryCacheEnabled || diskCacheEnabled || distributedCacheEnabled | sqliteCacheEnabled) { cacheKey = await imageJobInfo.GetFastCacheKey(); if (context.Request.Headers.TryGetValue(HeaderNames.IfNoneMatch, out var etag) && cacheKey == etag) { context.Response.StatusCode = StatusCodes.Status304NotModified; context.Response.ContentLength = 0; context.Response.ContentType = null; return; } } try { if (sqliteCacheEnabled) { await ProcessWithSqliteCache(context, cacheKey, imageJobInfo); } else if (diskCacheEnabled) { await ProcessWithDiskCache(context, cacheKey, imageJobInfo); } else if (memoryCacheEnabled) { await ProcessWithMemoryCache(context, cacheKey, imageJobInfo); // ReSharper disable once ConditionIsAlwaysTrueOrFalse } else if (distributedCacheEnabled) { await ProcessWithDistributedCache(context, cacheKey, imageJobInfo); } else { await ProcessWithNoCache(context, imageJobInfo); } } catch (BlobMissingException e) { await NotFound(context, e); } }
// ReSharper disable once UnusedMember.Global public async Task Invoke(HttpContext context) { // For instrumentation globalInfoProvider.CopyHttpContextInfo(context); var path = context.Request.Path; // Delegate to the diagnostics page if it is requested if (DiagnosticsPage.MatchesPath(path.Value)) { await diagnosticsPage.Invoke(context); return; } // Delegate to licenses page if requested if (licensePage.MatchesPath(path.Value)) { await licensePage.Invoke(context); return; } // Respond to /imageflow.ready if ("/imageflow.ready".Equals(path.Value, StringComparison.Ordinal)) { options.Licensing.FireHeartbeat(); using (new JobContext()) { await StringResponseNoCache(context, 200, "Imageflow.Server is ready to accept requests."); } return; } // Respond to /imageflow.health if ("/imageflow.health".Equals(path.Value, StringComparison.Ordinal)) { options.Licensing.FireHeartbeat(); await StringResponseNoCache(context, 200, "Imageflow.Server is healthy."); return; } // We only handle requests with an image extension or if we configured a path prefix for which to handle // extensionless requests if (!ImageJobInfo.ShouldHandleRequest(context, options)) { await next.Invoke(context); return; } options.Licensing.FireHeartbeat(); var imageJobInfo = new ImageJobInfo(context, options, blobProvider); if (!imageJobInfo.Authorized) { await NotAuthorized(context, imageJobInfo.AuthorizedMessage); return; } if (imageJobInfo.LicenseError) { if (options.EnforcementMethod == EnforceLicenseWith.Http422Error) { await StringResponseNoCache(context, 422, options.Licensing.InvalidLicenseMessage); return; } if (options.EnforcementMethod == EnforceLicenseWith.Http402Error) { await StringResponseNoCache(context, 402, options.Licensing.InvalidLicenseMessage); return; } } // If the file is definitely missing hand to the next middleware // Remote providers will fail late rather than make 2 requests if (!imageJobInfo.PrimaryBlobMayExist()) { await next.Invoke(context); return; } string cacheKey = null; var cachingPath = imageJobInfo.NeedsCaching() ? options.ActiveCacheBackend : CacheBackend.NoCache; if (cachingPath != CacheBackend.NoCache) { cacheKey = await imageJobInfo.GetFastCacheKey(); if (context.Request.Headers.TryGetValue(HeaderNames.IfNoneMatch, out var etag) && cacheKey == etag) { GlobalPerf.Singleton.IncrementCounter("etag_hit"); context.Response.StatusCode = StatusCodes.Status304NotModified; context.Response.ContentLength = 0; context.Response.ContentType = null; return; } GlobalPerf.Singleton.IncrementCounter("etag_miss"); } try { switch (cachingPath) { case CacheBackend.ClassicDiskCache: await ProcessWithDiskCache(context, cacheKey, imageJobInfo); break; case CacheBackend.NoCache: await ProcessWithNoCache(context, imageJobInfo); break; case CacheBackend.StreamCache: await ProcessWithStreamCache(context, cacheKey, imageJobInfo); break; default: throw new ArgumentOutOfRangeException(); } GlobalPerf.Singleton.IncrementCounter("middleware_ok"); } catch (BlobMissingException e) { await NotFound(context, e); } catch (Exception e) { var errorName = e.GetType().Name; var errorCounter = "middleware_" + errorName; GlobalPerf.Singleton.IncrementCounter(errorCounter); GlobalPerf.Singleton.IncrementCounter("middleware_errors"); throw; } finally { // Increment counter for type of file served var imageExtension = PathHelpers.GetImageExtensionFromContentType(context.Response.ContentType); if (imageExtension != null) { GlobalPerf.Singleton.IncrementCounter("module_response_ext_" + imageExtension); } } }