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); } }