Enable HTTP compression with ASP.NET Web API
Asked Answered
U

3

14

We serve files for a website from our Asp .NET Web API:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var clientHostname = System.Configuration.ConfigurationManager.AppSettings["ClientHostname"];

        var staticFileOptions = new StaticFileOptions()
        {
            OnPrepareResponse = staticFileResponseContext =>
            {
                staticFileResponseContext.OwinContext.Response.Headers.Add("Cache-Control", new[] { "public", "max-age=0" });
            }
        };

        app.MapWhen(ctx => ctx.Request.Headers.Get("Host").Equals(clientHostname), app2 =>
        {
            app2.Use((context, next) =>
            {
                if (context.Request.Path.HasValue == false || context.Request.Path.ToString() == "/") // Serve index.html by default at root
                {
                    context.Request.Path = new PathString("/Client/index.html");
                }
                else // Serve file
                {
                    context.Request.Path = new PathString($"/Client{context.Request.Path}");
                }

                return next();
            });

            app2.UseStaticFiles(staticFileOptions);
        });
    }
}

I want to enable HTTP compression. According to this MSDN documentation

Use server-based response compression technologies in IIS, Apache, or Nginx where the performance of the middleware probably won't match that of the server modules. Use Response Compression Middleware when you're unable to use:

  • IIS Dynamic Compression module

  • Apache mod_deflate module

  • NGINX Compression and Decompression

  • HTTP.sys server (formerly called WebListener)

  • Kestrel

So I think the first preferable way to do this in my instance is with IIS Dynamic Compression Module. Accordingly, I tried this in my Web.config, as a test, following this example:

<configuration>
  <system.webServer>
    <httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files">
      <dynamicTypes>
        <add mimeType="*/*" enabled="true" />
      </dynamicTypes>
      <staticTypes>
        <add mimeType="*/*" enabled="true" />
      </staticTypes>
    </httpCompression>
  </system.webServer>
</configuration>

However, the response headers do not include Content-Encoding, so I don't believe it is being compressed. What am I missing? How can I set this up to serve with compression in the best way possible?

I have verified that my client is sending an Accept-Encoding header of gzip, deflate, br.

Update

I tried installing Dynamic HTTP Compression in IIS as it is not installed by default. It seems to me I am trying to serve content statically, but I thought this was worth a try. I verified that both static and dynamic content compression are enabled in IIS Manager. However, I re-ran it but still no compression.

Update 2

I realized compression was working on our Azure servers but still not with my local IIS.

Unburden answered 13/10, 2017 at 21:18 Comment(2)
Instead of wildcard for all types, have you tried specific mime types in your configuration?Entero
@Entero Yes, I have, unfortunately to no avail.Unburden
O
2

I tried your startup in an empty 4.7 .NET web project, and I get compression, at least on index.html. I installed dynamic compression, added several Owin Packages, web.config below etc to get it working. Using IIS/10

packages.config

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="1.0.5" targetFramework="net47" />
  <package id="Microsoft.Net.Compilers" version="2.1.0" targetFramework="net47" developmentDependency="true" />
  <package id="Microsoft.Owin" version="3.1.0" targetFramework="net47" />
  <package id="Microsoft.Owin.FileSystems" version="3.1.0" targetFramework="net47" />
  <package id="Microsoft.Owin.Host.SystemWeb" version="3.1.0" targetFramework="net47" />
  <package id="Microsoft.Owin.StaticFiles" version="3.1.0" targetFramework="net47" />
  <package id="Owin" version="1.0" targetFramework="net47" />
</packages>

Web.config (worked for me without httpCompression)

<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  https://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>
  <appSettings>
    <add key="ClientHostname" value="localhost" />
    <add key="owin:appStartup" value="WebApplication22.App_Start.Startup" />
  </appSettings>
  <system.web>
    <compilation targetFramework="4.7" />
    <httpRuntime targetFramework="4.7" />
  </system.web>
  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" />
      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+" />
    </compilers>
  </system.codedom>
  <system.webServer>
    <httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files">
      <dynamicTypes>
        <add mimeType="*/*" enabled="true" />
      </dynamicTypes>
      <staticTypes>
        <add mimeType="*/*" enabled="true" />
      </staticTypes>
    </httpCompression>
  </system.webServer>
</configuration>

Startup.cs (abbreviated)

using Microsoft.Owin;
using Microsoft.Owin.StaticFiles;
using Owin;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace WebApplication22.App_Start
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            var clientHostname = System.Configuration.ConfigurationManager.AppSettings["ClientHostname"];

            var staticFileOptions = new StaticFileOptions()
            {
                OnPrepareResponse = staticFileResponseContext =>
                {
                    staticFileResponseContext.OwinContext.Response.Headers.Add("Cache-Control", new[] { "public", "max-age=0" });
                }
            };
            ...
            }
    }
}

Response

HTTP/1.1 200 OK
Cache-Control: public,max-age=0
Content-Type: text/html
Content-Encoding: gzip
Last-Modified: Tue, 17 Oct 2017 22:03:20 GMT
ETag: "1d347b5453aa6fa"
Vary: Accept-Encoding
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
Date: Wed, 18 Oct 2017 02:27:34 GMT
Content-Length: 588
...
Omnirange answered 18/10, 2017 at 2:42 Comment(0)
D
1

I have found these three resources to be useful in configuring dynamic compression for IIS on either ASP.Net WCF and Web API pages. I presume it also works for .Net Core but I haven't yet tried. The first two are a bit old but the principles still apply:

https://blog.arvixe.com/how-to-enable-gzip-on-iis7/

https://www.hanselman.com/blog/EnablingDynamicCompressionGzipDeflateForWCFDataFeedsODataAndOtherCustomServicesInIIS7.aspx

https://learn.microsoft.com/en-us/iis/configuration/system.webserver/httpcompression/

Specifically:

  • Yes, you do need the Dynamic HTTP Compression module installed in IIS, and enabled
  • Ensure that Dynamic compression is checked in IIS Manager under [Your server]/ Compression: Enable Dynamic Compression
  • Double-check that the MIME type in the client's request header is specifically added in the Configuration Editor under system.webServer/httpCompression/dynamicTypes/, and that the type handler' Enabled property is set to True
  • Add the web.config entries as outlined in the links above and the other answer
Dyestuff answered 18/10, 2017 at 3:23 Comment(0)
F
0

Most probably this what is missing on your Windows Server (I assume you work on server Os) is installation of Web Server IIS Performance features in which there are two submodules which can be installed: Static Content Conpression and Dynamic Content Compression.

To check if they are installed run Server Manager, select Add Roles and Features, select your instance, in screen Server Roles expand tree nodes Web Server (IIS), Web Server, Performance and verify if checkboxes indicate that Static Content Conpression and Dynamic Content Compression are installed if not check them and continue with feature installation. Then repeat all setup steps for static and dynamic compression configuration in IIS Manager and in Web Site settings. It should work now.

Fichte answered 21/10, 2017 at 22:30 Comment(2)
My OS is Windows 10 Home, so I'm not sure where to find Server Manager?Unburden
OK it changes problem a bit and makes my above answer useless. To check if you have required functionality in IIS installed go to Control Panel -> Program and Features -> Turn Windows Features on or off -> find Internet Information Services node and expand it -> expand World Wide Web Services node -> expand Performance Features node - and verify that both check boxes for Dynamic and Static Content Compression are checked -> if not check them and proceed with installation.Fichte

© 2022 - 2024 — McMap. All rights reserved.