예제 #1
0
        private async Task ManageES5Conversion(HttpContext context)
        {
            //If this return true here, this mean this is a subsequent call to a file
            //and that the file has already been cached in the internal dictionary
            //Otherwise we must try to seek the file hash of the current request and see
            //if it has been converted at least once in the app lifetime
            if (ES5CacheHelper.HasES5FileInCacheByPath(context.Request.Path))
            {
                var fileCache = ES5CacheHelper.GetES5FileFromCache(context.Request.Path);

                //Manage request specificity
                await HttpRequestManager.ManageRequest(context, fileCache.ES5Path, fileCache.ETag, fileCache.ContentLength);

                return;
            }

            //Here we are tricking the StaticFile handler by modifying the Body Stream type before it try to write in it.
            //Using a MemoryStream in order to be able to catch and modify the content afterward
            var originalResponseStream = context.Response.Body;

            using (var fakeResponseStream = new MemoryStream())
            {
                context.Response.Body = fakeResponseStream;

                //Awaiting StaticFile to fill the content
                await _next(context);

                //If the requested file return 304 status code, we should not try to cache / resolve this file
                //as StaticFileMiddleware does not return the data in this case
                //Same as if there is any other behavior that is not a success (not 200) we must retrieve and return the initial stream modified by the other context
                //without any alteration
                if (context.Response.StatusCode != 200)
                {
                    //Restoring the original response WriteOnly Stream
                    context.Response.Body = await CopyStreamAsync(fakeResponseStream, originalResponseStream);

                    return;
                }

                var response = await ExtractResponseAsync(context.Request, context.Response);

                RequestFileCacheMetadata _cacheMetadata = null;

                //From here we must see if we have a corresponding hash for this fetched resource in the cache store. Subsequent call will short-circuit at the top of this method because
                //the cache entry dictionary will be populated. If the data is not present we will have
                //to cache the file in disk
                if (ES5CacheHelper.HasES5FileInCacheWithChecksum(context.Request.Path, response.SourceCheckSum))
                {
                    _cacheMetadata = ES5CacheHelper.GetES5FileFromCache(context.Request.Path);
                }
                else
                {
                    //Convert to ES5 the current response
                    var fileContent = ES5Convert(response);

                    if (fileContent == null)
                    {
                        //If here that mean that conversion failed.
                        //We will take the original object but will add
                        //current content as ES5 even if not
                        fileContent            = response;
                        fileContent.ES5Content = fileContent.SourceContent;
                    }

                    _cacheMetadata = ES5CacheHelper.SetES5FileInCache(fileContent);
                }

                //As we have interverted the original Http Stream in our 'using' above, we
                //must restore it in order to make the thing work normally
                context.Response.Body = originalResponseStream;

                //Manage request specificity
                await HttpRequestManager.ManageRequest(context, _cacheMetadata.ES5Path, _cacheMetadata.ETag, _cacheMetadata.ContentLength);
            }
        }