Exemplo n.º 1
0
        /// <summary>
        /// Returns an IVirtualFileAsync instance if the specified file can be provided by an async provider
        /// </summary>
        /// <param name="virtualPath"></param>
        /// <param name="queryString"></param>
        /// <returns></returns>
        public async Task <IVirtualFileAsync> GetFileAsync(string virtualPath, NameValueCollection queryString)
        {
            IVirtualFileAsync f = null;

            foreach (IVirtualImageProviderAsync p in c.Plugins.GetAll <IVirtualImageProviderAsync>())
            {
                if (await p.FileExistsAsync(virtualPath, queryString))
                {
                    f = await p.GetFileAsync(virtualPath, queryString);

                    break;
                }
            }
            if (f == null)
            {
                return(null);
            }
            try
            {
                //Now we have a reference to the real virtual file, let's see if it is source-cached.
                IVirtualFileAsync cached = null;
                foreach (IVirtualFileCacheAsync p in c.Plugins.GetAll <IVirtualFileCacheAsync>())
                {
                    cached = await p.GetFileIfCachedAsync(virtualPath, queryString, f);

                    if (cached != null)
                    {
                        return(cached);
                    }
                }
            }catch (FileNotFoundException)
            {
                //IVirtualFileCache instances will .Open() and read the original IVirtualFile instance.
                return(null);
            }
            return(f);
        }
Exemplo n.º 2
0
        protected async Task CheckRequest_PostAuthorizeRequest_Async(object sender, EventArgs e)
        {
            //Skip requests if the Request object isn't populated
            HttpApplication app = sender as HttpApplication;

            if (app == null || app.Context == null || app.Context.Request == null)
            {
                return;
            }


            var ra = new HttpModuleRequestAssistant(app.Context, conf, this);

            var result = ra.PostAuthorize();

            if (result == HttpModuleRequestAssistant.PostAuthorizeResult.UnrelatedFileType)
            {
                return; //Exit early, not our scene
            }

            if (result == HttpModuleRequestAssistant.PostAuthorizeResult.AccessDenied403)
            {
                ra.FireAccessDenied();
                throw new ImageProcessingException(403, "Access denied", "Access denied");
            }

            if (result == HttpModuleRequestAssistant.PostAuthorizeResult.Complete)
            {
                //Does the file exist physically? (false if VppUsage=always or file is missing)
                bool existsPhysically = (conf.VppUsage != VppUsageOption.Always);
                if (existsPhysically)
                {
                    existsPhysically = File.Exists(ra.RewrittenMappedPath);
                }

                //If not present physically (and VppUsage!=never), try to get the virtual file. Null indicates a missing file
                IVirtualFileAsync vf = null;

                if (conf.VppUsage != VppUsageOption.Never && !existsPhysically)
                {
                    vf = await conf.GetFileAsync(ra.RewrittenVirtualPath, ra.RewrittenQuery);
                }

                //Only process files that exist
                if (!existsPhysically && vf == null)
                {
                    ra.FireMissing();
                    return;
                }

                try
                {
                    await HandleRequest(app.Context, ra, vf);

                    //Catch not found exceptions
                    ra.FirePostAuthorizeSuccess();
                }
                catch (System.IO.FileNotFoundException notFound)
                { //Some VPPs are optimistic, or could be a race condition
                    if (notFound.Message.Contains(" assembly "))
                    {
                        throw;                                          //If an assembly is missing, it should be a 500, not a 404
                    }
                    ra.FireMissing();
                    throw new ImageMissingException("The specified resource could not be located", "File not found", notFound);
                }
                catch (System.IO.DirectoryNotFoundException notFound)
                {
                    ra.FireMissing();
                    throw new ImageMissingException("The specified resource could not be located", "File not found", notFound);
                }
                catch (Exception ex)
                {
                    ra.FirePostAuthorizeRequestException(ex);
                    throw;
                }
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Generates the resized image to disk (if needed), then rewrites the request to that location.
        /// Perform 404 checking before calling this method. Assumes file exists.
        /// Called during PostAuthorizeRequest
        /// </summary>
        /// <param name="context"></param>
        /// <param name="ra"></param>
        /// <param name="vf"></param>
        protected virtual async Task HandleRequest(HttpContext context, HttpModuleRequestAssistant ra, IVirtualFileAsync vf)
        {
            if (!ra.CachingIndicated && !ra.ProcessingIndicated)
            {
                ra.ApplyRewrittenPath(); //This is needed for both physical and virtual files; only makes changes if needed.
                if (vf != null)
                {
                    ra.AssignSFH(); //Virtual files are not served in .NET 4.
                }
                return;
            }


            //Communicate to the MVC plugin this request should not be affected by the UrlRoutingModule.
            context.Items[conf.StopRoutingKey]  = true;
            context.Items[conf.ResponseArgsKey] = ""; //We are handling the request


            ra.EstimateResponseInfo();



            //Build CacheEventArgs
            var e = new AsyncResponsePlan();

            var modDate = (vf == null) ? System.IO.File.GetLastWriteTimeUtc(ra.RewrittenMappedPath) :
                          (vf is IVirtualFileWithModifiedDateAsync ? await((IVirtualFileWithModifiedDateAsync)vf).GetModifiedDateUTCAsync() : DateTime.MinValue);

            e.RequestCachingKey = ra.GenerateRequestCachingKey(modDate);

            var settings = new ResizeSettings(ra.RewrittenInstructions);

            e.RewrittenQuerystring   = settings;
            e.EstimatedContentType   = ra.EstimatedContentType;
            e.EstimatedFileExtension = ra.EstimatedFileExtension;



            //A delegate for accessing the source file
            e.OpenSourceStreamAsync = async delegate()
            {
                return((vf != null) ? await vf.OpenAsync() : File.Open(ra.RewrittenMappedPath, FileMode.Open, FileAccess.Read, FileShare.Read));
            };

            //Add delegate for writing the data stream
            e.CreateAndWriteResultAsync = async delegate(System.IO.Stream stream, IAsyncResponsePlan plan)
            {
                //This runs on a cache miss or cache invalid. This delegate is preventing from running in more
                //than one thread at a time for the specified cache key
                try
                {
                    if (!ra.ProcessingIndicated)
                    {
                        //Just duplicate the data
                        using (Stream source = await e.OpenSourceStreamAsync())
                            await source.CopyToAsync(stream); //4KiB buffer
                    }
                    else
                    {
                        MemoryStream inBuffer = null;
                        using (var sourceStream = vf != null ? await vf.OpenAsync() : File.Open(ra.RewrittenMappedPath, FileMode.Open, FileAccess.Read, FileShare.Read))
                        {
                            inBuffer = new MemoryStream(sourceStream.CanSeek ? (int)sourceStream.Length : 128 * 1024);
                            await sourceStream.CopyToAsync(inBuffer);
                        }
                        inBuffer.Seek(0, SeekOrigin.Begin);

                        var outBuffer = new MemoryStream(32 * 1024);

                        //Handle I/O portions of work asynchronously.
                        var j = new ImageJob
                        {
                            Instructions   = new Instructions(settings),
                            SourcePathData = vf != null ? vf.VirtualPath : ra.RewrittenVirtualPath,
                            Dest           = outBuffer,
                            Source         = inBuffer
                        };

                        await conf.GetImageBuilder().BuildAsync(j, int.MaxValue, CancellationToken.None);

                        outBuffer.Seek(0, SeekOrigin.Begin);
                        await outBuffer.CopyToAsync(stream);
                    }
                    ra.FireJobSuccess();
                    //Catch not found exceptions
                }
                catch (System.IO.FileNotFoundException notFound)
                {
                    if (notFound.Message.Contains(" assembly "))
                    {
                        throw;                                          //If an assembly is missing, it should be a 500, not a 404
                    }
                    //This will be called later, if at all.
                    ra.FireMissing();
                    throw new ImageMissingException("The specified resource could not be located", "File not found", notFound);
                }
                catch (System.IO.DirectoryNotFoundException notFound)
                {
                    ra.FireMissing();
                    throw new ImageMissingException("The specified resource could not be located", "File not found", notFound);
                }
                catch (Exception ex)
                {
                    ra.FireJobException(ex);
                    throw;
                }
            };



            //All bad from here down....
            context.Items[conf.ResponseArgsKey] = e; //store in context items

            //Fire events (for client-side caching plugins)
            conf.FirePreHandleImageAsync(this, context, e);

            //Pass the rest of the work off to the caching module. It will handle rewriting/redirecting and everything.
            //We handle request headers based on what is found in context.Items
            IAsyncTyrantCache cache = conf.GetAsyncCacheFor(context, e);

            //Verify we have a caching system
            if (cache == null)
            {
                throw new ImageProcessingException("Image Resizer: No async caching plugin was found for the request");
            }

            await cache.ProcessAsync(context, e);
        }
Exemplo n.º 4
0
        public async Task <IVirtualFileAsync> GetFileIfCachedAsync(string virtualPath, NameValueCollection queryString, IVirtualFileAsync original)
        {
            //Use alternate cache key if provided
            string key = original is IVirtualFileSourceCacheKey ? ((IVirtualFileSourceCacheKey)original).GetCacheKey(true) : original.VirtualPath;
            //If cached, serve it.
            CachedVirtualFile c = cache.Get(key);

            if (c != null)
            {
                return(c);
            }
            //If not, let's cache it.
            if ("mem".Equals(queryString["scache"], StringComparison.OrdinalIgnoreCase))
            {
                await asyncLocks.TryExecuteAsync(key, 3000, async delegate()
                {
                    c = cache.Get(key);
                    if (c == null)
                    {
                        using (Stream data = await original.OpenAsync())
                        {//Very long-running call
                            c = new CachedVirtualFile(original.VirtualPath, await data.CopyToBytesAsync(true, 0x1000));
                        }
                        cache.Set(key, c);//Save to cache (may trigger cleanup)
                    }
                });

                return(c);
            }
            return(null);
        }
Exemplo n.º 5
0
        public Task <IVirtualFileAsync> GetFileAsync(string virtualPath, NameValueCollection queryString)
        {
            IVirtualFileAsync blobImage = GetBlobFile(virtualPath, queryString);

            return(Task.FromResult(blobImage));
        }
Exemplo n.º 6
0
        public async Task <IVirtualFileAsync> GetFileIfCachedAsync(string virtualPath, NameValueCollection queryString, IVirtualFileAsync original)
        {
            if (!"disk".Equals(queryString["scache"], StringComparison.OrdinalIgnoreCase))
            {
                return(null);
            }
            if (!this.AsyncModuleMode)
            {
                throw new InvalidOperationException("SourceDiskCache cannot be used in asynchronous mode if AsyncModuleMode=false");
            }


            //Verify web.config exists in the cache folder.
            writer.CheckWebConfigEvery5();

            //Use alternate cache key if provided
            string key = original is IVirtualFileSourceCacheKey ? ((IVirtualFileSourceCacheKey)original).GetCacheKey(false) : original.VirtualPath;
            //If cached, serve it.
            var r = await asyncCache.GetCachedFile(key, ".cache", async delegate(Stream target)
            {
                using (Stream data = await original.OpenAsync())
                {//Very long-running call
                    await data.CopyToAsync(target);
                }
            }, 15 * 1000, true);

            if (r.Result == CacheQueryResult.Failed)
            {
                return(null);
            }

            if (r.Result == CacheQueryResult.Hit && cleaner != null)
            {
                cleaner.UsedFile(r.RelativePath, r.PhysicalPath);
            }


            return(new SourceVirtualFileAsync(original.VirtualPath, delegate()
            {
                return Task.FromResult(r.Data ?? File.Open(r.PhysicalPath, FileMode.Open, FileAccess.Read, FileShare.Read));
            }));
        }