Exemplo n.º 1
0
        public ImageflowMiddleware(
            RequestDelegate next,
            IWebHostEnvironment env,
            IEnumerable <ILogger <ImageflowMiddleware> > logger,
            IEnumerable <IMemoryCache> memoryCache,
            IEnumerable <IDistributedCache> distributedCache,
            IEnumerable <ISqliteCache> sqliteCaches,
            IEnumerable <IClassicDiskCache> diskCache,
            IEnumerable <IBlobProvider> blobProviders,
            ImageflowMiddlewareOptions options)
        {
            this.next             = next;
            this.options          = options;
            this.env              = env;
            this.logger           = logger.FirstOrDefault();
            this.memoryCache      = memoryCache.FirstOrDefault();
            this.diskCache        = diskCache.FirstOrDefault();
            this.distributedCache = distributedCache.FirstOrDefault();
            this.sqliteCache      = sqliteCaches.FirstOrDefault();
            var providers   = blobProviders.ToList();
            var mappedPaths = options.MappedPaths.ToList();

            if (options.MapWebRoot)
            {
                if (this.env?.WebRootPath == null)
                {
                    throw new InvalidOperationException("Cannot call MapWebRoot if env.WebRootPath is null");
                }
                mappedPaths.Add(new PathMapping("/", this.env.WebRootPath));
            }

            blobProvider    = new BlobProvider(providers, mappedPaths);
            diagnosticsPage = new DiagnosticsPage(env, this.logger, this.memoryCache, this.distributedCache, this.diskCache, providers);
        }
Exemplo n.º 2
0
        public ImageflowMiddleware(
            RequestDelegate next,
            IWebHostEnvironment env,
            IEnumerable <ILogger <ImageflowMiddleware> > logger,
            IEnumerable <IClassicDiskCache> diskCaches,
            IEnumerable <IStreamCache> streamCaches,
            IEnumerable <IBlobProvider> blobProviders,
            ImageflowMiddlewareOptions options)
        {
            this.next = next;
            options.Licensing ??= new Licensing(LicenseManagerSingleton.GetOrCreateSingleton(
                                                    "imageflow_", new[] { env.ContentRootPath, Path.GetTempPath() }));
            this.options = options;
            this.env     = env;
            this.logger  = logger.FirstOrDefault();
            diskCache    = diskCaches.FirstOrDefault();

            var streamCacheArray = streamCaches.ToArray();

            if (streamCacheArray.Count() > 1)
            {
                throw new InvalidOperationException("Only 1 IStreamCache instance can be registered at a time");
            }

            streamCache = streamCacheArray.FirstOrDefault();


            var providers   = blobProviders.ToList();
            var mappedPaths = options.MappedPaths.ToList();

            if (options.MapWebRoot)
            {
                if (this.env?.WebRootPath == null)
                {
                    throw new InvalidOperationException("Cannot call MapWebRoot if env.WebRootPath is null");
                }
                mappedPaths.Add(new PathMapping("/", this.env.WebRootPath));
            }

            //Determine the active cache backend
            var streamCacheEnabled = streamCache != null && options.AllowCaching;
            var diskCacheEnabled   = this.diskCache != null && options.AllowDiskCaching;

            if (streamCacheEnabled)
            {
                options.ActiveCacheBackend = CacheBackend.StreamCache;
            }
            else if (diskCacheEnabled)
            {
                options.ActiveCacheBackend = CacheBackend.ClassicDiskCache;
            }
            else
            {
                options.ActiveCacheBackend = CacheBackend.NoCache;
            }


            options.Licensing.Initialize(this.options);

            blobProvider       = new BlobProvider(providers, mappedPaths);
            diagnosticsPage    = new DiagnosticsPage(options, env, this.logger, streamCache, this.diskCache, providers);
            licensePage        = new LicensePage(options);
            globalInfoProvider = new GlobalInfoProvider(options, env, this.logger, streamCache, this.diskCache, providers);

            options.Licensing.FireHeartbeat();
            GlobalPerf.Singleton.SetInfoProviders(new List <IInfoProvider>()
            {
                globalInfoProvider
            });
        }
Exemplo n.º 3
0
        // 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);
                }
            }
        }