/// <summary> /// Get the info about the resource that in the assembly /// </summary> /// <param name="assembly"></param> /// <param name="resourceName"></param> /// <returns></returns> protected static Quadruplet <bool, bool, string, bool> GetResourceInfo(Assembly assembly, string resourceName) { // Create a unique cache key var cacheKey = CombineHashCodes(assembly.GetHashCode(), resourceName.GetHashCode()); var resourceInfo = WebResourceCache[cacheKey] as Quadruplet <bool, bool, string, bool>; // Assembly info was not in the cache if (resourceInfo == null) { var first = false; var second = false; var third = string.Empty; var forth = false; var customAttributes = assembly.GetCustomAttributes(false); for (var j = 0; j < customAttributes.Length; j++) { var attribute = customAttributes[j] as WebResourceAttribute; if ((attribute == null) || !string.Equals(attribute.WebResource, resourceName, StringComparison.Ordinal)) { continue; } first = true; second = attribute.PerformSubstitution; third = attribute.ContentType; forth = CompressionModuleHelper.IsContentTypeCompressible(attribute.ContentType); break; } resourceInfo = new Quadruplet <bool, bool, string, bool>(first, second, third, forth); WebResourceCache[cacheKey] = resourceInfo; } return(resourceInfo); }
/// <summary> /// Write a StreamReader to an outpit stream /// </summary> /// <param name="reader"></param> /// <param name="context"></param> protected static void CompressAndWriteToStream(StreamReader reader, HttpContext context) { var compressionType = CompressionModuleHelper.IsSpecificEncodingSupported(context, CompressionModuleHelper.GZIP) ? CompressionModuleHelper.GZIP : CompressionModuleHelper.DEFLATE; CompressionModuleHelper.SetEncodingType(context.Response, compressionType); // All the supported content for compression can be read as string, so we use reader.ReadToEnd() var compressed = CompressionModuleHelper.Compressor(reader.ReadToEnd(), compressionType); context.Response.OutputStream.Write(compressed, 0, compressed.Length); reader.Dispose(); }
protected static void OnPostAcquireRequestState(object sender, EventArgs e) { var httpContext = HttpContext.Current; // This part of the module compress only handlers from type System.Web.UI.Page // Other types such JavaScript or CSS files will be compressed in an httpHandler. // Here we check if the current handler if a Page, if so, we compress it. // Because there is a problem with async postbacks compression, we check here if the current request if an 'MS AJAX' call. // If so, we will not compress it. // Important !!! : I didn't check this module with another Ajax frameworks such 'infragistics' or 'SmartClient'. // probably you will have to change the IsAjaxPostBackRequest method. if (!(httpContext.CurrentHandler is Page || httpContext.CurrentHandler.GetType().BaseType.FullName == "System.Web.Mvc.MvcHandler") || CompressionModuleHelper.IsAjaxPostBackRequest(httpContext)) { return; } if (!CompressionModuleHelper.IsCompressionSupported(httpContext, true)) { return; } var response = httpContext.Response; // Check if GZIP is supported by the client if (CompressionModuleHelper.IsSpecificEncodingSupported(httpContext, CompressionModuleHelper.GZIP)) { response.Filter = new GZipStream(response.Filter, CompressionMode.Compress); CompressionModuleHelper.SetEncodingType(response, CompressionModuleHelper.GZIP); } // If GZIP is not supported, so only DEFLATE is. else { response.Filter = new DeflateStream(response.Filter, CompressionMode.Compress); CompressionModuleHelper.SetEncodingType(response, CompressionModuleHelper.DEFLATE); } }
protected static void OnPreRequestHandlerExecute(object sender, EventArgs e) { var httpApplication = (HttpApplication)sender; var httpContext = httpApplication.Context; if (!(httpContext.CurrentHandler is AssemblyResourceLoader)) { return; } var response = httpContext.Response; var request = httpContext.Request; var etag = (request.QueryString.ToString()).GetHashCode().ToString(); // Check if the ETag is match. If so, we don't send nothing to the client, and stop here. CheckETag(httpApplication, etag); try { // Parse the QueryString into parts var urlInfo = GetDataFromQuery(httpApplication.Context.Request.QueryString); // Load the assembly var assembly = GetAssembly(urlInfo.First, urlInfo.Second); if (assembly == null) { ThrowHttpException(404, SR.WebResourceCompressionModuleAssemblyNotFound, urlInfo.Forth); } //var lastModified = File.GetLastWriteTimeUtc(assembly.Location); // Get the resource info from assembly. var resourceInfo = GetResourceInfo(assembly, urlInfo.Third); if (!resourceInfo.First) { ThrowHttpException(404, SR.WebResourceCompressionModuleAssemblyNotFound, urlInfo.Forth); } // If the WebResource needs to perform substitution (WebResource inside WebResource), we leave it to the original AssemblyResourceLoader handler ;-) if (resourceInfo.Second) { return; } response.Clear(); // Set the response cache headers SetCachingHeadersForWebResource(response.Cache, etag, Expires); // Set the response content type response.ContentType = resourceInfo.Third; // Write content with compression if (resourceInfo.Forth && CompressionModuleHelper.IsCompressionSupported(httpContext, false)) { using (var resourceStream = new StreamReader(assembly.GetManifestResourceStream(urlInfo.Third), true)) { CompressAndWriteToStream(resourceStream, httpApplication.Context); } } // Write content without compression else { using (var resourceStream = assembly.GetManifestResourceStream(urlInfo.Third)) { WriteToStream(resourceStream, response.OutputStream); } } response.OutputStream.Flush(); httpApplication.CompleteRequest(); } catch (ArgumentNullException) { return; } catch (TargetInvocationException) { return; } catch (System.Security.Cryptography.CryptographicException) { return; } }