Owin.Compression


Owin.Compression

Owin.Compression (Deflate / GZip) module ("middleware") for Microsoft OWIN pipeline. Can be used with .NET Full, .NET Core, .NET Standard, .NET6.0, and so on. Works with Selfhost and AspNetCore (e.g. with Kestrel, which is OWIN based server). It compresses the web request responses to make the transfer smaller, and it supports eTag caching.

The Owin.Compression library can be installed from NuGet:
PM> Install-Package Owin.Compression

Default compression used is deflate, then gzip, as deflate should be faster.

eTag-caching

  1. When the server reads the content before compression, it calculates a hash-code over it.
  2. The hash-code is sent as ETag response header to the client with the response
  3. The next time the client asks the same resource, it sends an If-None-Match header in the request with the same value.
  4. After the server reads the content before the compression, it calculates a hash-code over it. If it matches the If-None-Match of the request, the server can skip the compression and skip the sending and just send http status code 304 to the client which means "use what you have, it's not modified since".

Example #1

This example demonstrates using MapCompressionModule-function defined in this sample library.

  using System;
  using Owin;
  [assembly: Microsoft.Owin.OwinStartup(typeof(MyServer.MyWebStartup))]
  namespace MyServer
  {
    class MyWebStartup
    {
      public void Configuration(Owin.IAppBuilder app)
      {
                // This will compress the whole request, if you want to use e.g. Microsoft.Owin.StaticFiles server:
                // app.UseCompressionModule()

        var settings = OwinCompression.DefaultCompressionSettingsWithPath("c:\\temp\\"); //" server path
        //or var settings = new CompressionSettings( ... )
        app.MapCompressionModule("/zipped", settings);
      }
    }

    class Program
    {
      static void Main(string[] args)
      {
        Microsoft.Owin.Hosting.WebApp.Start<MyWebStartup>("http://*:8080"); //" run on localhost.
        Console.WriteLine("Server started... Press enter to exit.");
        Console.ReadLine();
      }
    }
  }

And now your files are smaller than with e.g. just Microsoft.Owin.StaticFiles -library server:

compressed

Even though the browser sees everything as plain text, the traffic is actually transfered as compressed format. You can monitor the traffic with e.g. Fiddler.

Example #2

Running on OWIN Self-Host (Microsoft.Owin.Hosting) with static files server (Microsoft.Owin.StaticFiles) and compressing only the ".json"-responses (and files) on-the-fly, with only gzip and not deflate:

  using System;
  using Owin;
  [assembly: Microsoft.Owin.OwinStartup(typeof(MyServer.MyWebStartup))]
  namespace MyServer
  {
    class MyWebStartup
    {
      public void Configuration(Owin.IAppBuilder app)
      {
        var settings = new CompressionSettings(
          serverPath: "", 
          allowUnknonwnFiletypes: false,
          allowRootDirectories: false, 
          cacheExpireTime: Microsoft.FSharp.Core.FSharpOption<DateTimeOffset>.None, 
          allowedExtensionAndMimeTypes:
            new[] { Tuple.Create(".json", "application/json") },
          minimumSizeToCompress: 1000, 
          streamingDisabled: false,
          deflateDisabled: true
          );
        app.UseCompressionModule(settings);
      }
    }

    class Program
    {
      static void Main(string[] args)
      {
        Microsoft.Owin.Hosting.WebApp.Start<MyWebStartup>("http://*:8080");
        Console.WriteLine("Server started... Press enter to exit.");
        Console.ReadLine();
      }
    }
  }

Example #3

Running on OWIN Self-Host (Microsoft.Owin.Hosting) with static files server (Microsoft.Owin.StaticFiles) and compressing all the responses (and files) on-the-fly. This example is in F-Sharp (and can be run with F#-interactive):

#r "Owin.dll"
#r "Microsoft.Owin.dll"
#r "Microsoft.Owin.FileSystems.dll"
#r "Microsoft.Owin.Hosting.dll"
#r "Microsoft.Owin.StaticFiles.dll"
#r "System.Configuration.dll"
#r "Owin.Compression.dll"

open Owin
open System

module Examples =

type MyStartup() =
    member __.Configuration(app:Owin.IAppBuilder) =
        let app1 = app.UseCompressionModule()
        app1.UseFileServer "/." |> ignore
        ()

let server = Microsoft.Owin.Hosting.WebApp.Start<MyStartup> "http://*:6000"
Console.WriteLine "Press Enter to stop & quit."
Console.ReadLine() |> ignore
server.Dispose()

Example #4

Running on ASP.NET Core web API on .NET 6.0. You can use C# but this example is in F# just because shorter syntax. The full project is available at tests-folder of this project:

open System
open Microsoft.AspNetCore.Builder
open Microsoft.Extensions.DependencyInjection
open Microsoft.Extensions.Hosting
open Owin

module Program =

    [<EntryPoint>]
    let main args =

        let builder = WebApplication.CreateBuilder args
        builder.Services.AddControllers() |> ignore
        let app = builder.Build()

        let compressionSetting = 
            {OwinCompression.DefaultCompressionSettings with 
                CacheExpireTime = Some (DateTimeOffset.Now.AddDays 7.)
                AllowUnknonwnFiletypes = true
                StreamingDisabled = true
            }
        (app :> IApplicationBuilder).UseCompressionModule(compressionSetting) |> ignore 
        app.MapControllers() |> ignore
        app.Run()
        0

https://github.com/Thorium/Owin.Compression/tree/master/tests/Aspnet.Core.WebAPI.Test

Example #5

More complete example can be found here.

Samples & documentation

The library comes with comprehensible documentation. It can include tutorials automatically generated from *.fsx files in the content folder. The API reference is automatically generated from Markdown comments in the library implementation.

Contributing and copyright

The project is hosted on GitHub where you can report issues, fork the project and submit pull requests. If you're adding a new public API, please also consider adding samples that can be turned into a documentation. You might also want to read the library design notes to understand how it works.

The library is available under Public Domain license, which allows modification and redistribution for both commercial and non-commercial purposes. For more information see the License file in the GitHub repository.

namespace Owin
namespace System
module Examples from Index
Multiple items
type MyStartup = new: unit -> MyStartup member Configuration: app: IAppBuilder -> unit

--------------------
new: unit -> MyStartup
val app: IAppBuilder
type IAppBuilder = member Build: returnType: Type -> obj member New: unit -> IAppBuilder member Use: middleware: obj * [<ParamArray>] args: obj[] -> IAppBuilder member Properties: IDictionary<string,obj>
val app1: obj
val ignore: value: 'T -> unit
<summary>Ignore the passed value. This is often used to throw away results of a computation.</summary>
<param name="value">The value to ignore.</param>
<example id="min-example"><code lang="fsharp"> ignore 55555 // Evaluates to () </code></example>
val server: IDisposable
namespace Microsoft
namespace Microsoft.Owin
namespace Microsoft.Owin.Hosting
type WebApp = static member Start: url: string * startup: Action<IAppBuilder> -> IDisposable + 5 overloads
<summary> These methods are used to load, assemble, and start a web app. </summary>
Owin.Hosting.WebApp.Start(options: Owin.Hosting.StartOptions) : IDisposable
Owin.Hosting.WebApp.Start(url: string) : IDisposable
Owin.Hosting.WebApp.Start<'TStartup>(options: Owin.Hosting.StartOptions) : IDisposable
Owin.Hosting.WebApp.Start<'TStartup>(url: string) : IDisposable
Owin.Hosting.WebApp.Start(options: Owin.Hosting.StartOptions, startup: Action<IAppBuilder>) : IDisposable
Owin.Hosting.WebApp.Start(url: string, startup: Action<IAppBuilder>) : IDisposable
type Console = static member Beep: unit -> unit + 1 overload static member Clear: unit -> unit static member GetCursorPosition: unit -> struct (int * int) static member MoveBufferArea: sourceLeft: int * sourceTop: int * sourceWidth: int * sourceHeight: int * targetLeft: int * targetTop: int -> unit + 1 overload static member OpenStandardError: unit -> Stream + 1 overload static member OpenStandardInput: unit -> Stream + 1 overload static member OpenStandardOutput: unit -> Stream + 1 overload static member Read: unit -> int static member ReadKey: unit -> ConsoleKeyInfo + 1 overload static member ReadLine: unit -> string ...
<summary>Represents the standard input, output, and error streams for console applications. This class cannot be inherited.</summary>
Console.WriteLine() : unit
   (+0 other overloads)
Console.WriteLine(value: uint64) : unit
   (+0 other overloads)
Console.WriteLine(value: uint32) : unit
   (+0 other overloads)
Console.WriteLine(value: string) : unit
   (+0 other overloads)
Console.WriteLine(value: float32) : unit
   (+0 other overloads)
Console.WriteLine(value: obj) : unit
   (+0 other overloads)
Console.WriteLine(value: int64) : unit
   (+0 other overloads)
Console.WriteLine(value: int) : unit
   (+0 other overloads)
Console.WriteLine(value: float) : unit
   (+0 other overloads)
Console.WriteLine(value: decimal) : unit
   (+0 other overloads)
Console.ReadLine() : string
IDisposable.Dispose() : unit
namespace Microsoft.AspNetCore
namespace Microsoft.AspNetCore.Builder
namespace Microsoft.Extensions
Multiple items
type EntryPointAttribute = inherit Attribute new: unit -> EntryPointAttribute
<summary>Adding this attribute to a function indicates it is the entrypoint for an application. If this attribute is not specified for an EXE then the initialization implicit in the module bindings in the last file in the compilation sequence are used as the entrypoint.</summary>
<category>Attributes</category>


--------------------
new: unit -> EntryPointAttribute
val main: args: string[] -> int
val args: string[]
val builder: obj
val app: IApplicationBuilder
val compressionSetting: CompressionSettings
module OwinCompression from Owin
val DefaultCompressionSettings: CompressionSettings
union case Option.Some: Value: 'T -> Option<'T>
<summary>The representation of "Value of type 'T"</summary>
<param name="Value">The input value.</param>
<returns>An option representing the value.</returns>
Multiple items
[<Struct>] type DateTimeOffset = new: dateTime: DateTime -> unit + 8 overloads member Add: timeSpan: TimeSpan -> DateTimeOffset member AddDays: days: float -> DateTimeOffset member AddHours: hours: float -> DateTimeOffset member AddMicroseconds: microseconds: float -> DateTimeOffset member AddMilliseconds: milliseconds: float -> DateTimeOffset member AddMinutes: minutes: float -> DateTimeOffset member AddMonths: months: int -> DateTimeOffset member AddSeconds: seconds: float -> DateTimeOffset member AddTicks: ticks: int64 -> DateTimeOffset ...
<summary>Represents a point in time, typically expressed as a date and time of day, relative to Coordinated Universal Time (UTC).</summary>

--------------------
DateTimeOffset ()
DateTimeOffset(dateTime: DateTime) : DateTimeOffset
DateTimeOffset(dateTime: DateTime, offset: TimeSpan) : DateTimeOffset
DateTimeOffset(ticks: int64, offset: TimeSpan) : DateTimeOffset
DateTimeOffset(date: DateOnly, time: TimeOnly, offset: TimeSpan) : DateTimeOffset
DateTimeOffset(year: int, month: int, day: int, hour: int, minute: int, second: int, offset: TimeSpan) : DateTimeOffset
DateTimeOffset(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int, offset: TimeSpan) : DateTimeOffset
DateTimeOffset(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int, calendar: Globalization.Calendar, offset: TimeSpan) : DateTimeOffset
DateTimeOffset(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int, microsecond: int, offset: TimeSpan) : DateTimeOffset
DateTimeOffset(year: int, month: int, day: int, hour: int, minute: int, second: int, millisecond: int, microsecond: int, calendar: Globalization.Calendar, offset: TimeSpan) : DateTimeOffset
property DateTimeOffset.Now: DateTimeOffset with get
<summary>Gets a <see cref="T:System.DateTimeOffset" /> object that is set to the current date and time on the current computer, with the offset set to the local time's offset from Coordinated Universal Time (UTC).</summary>
<returns>A <see cref="T:System.DateTimeOffset" /> object whose date and time is the current local time and whose offset is the local time zone's offset from Coordinated Universal Time (UTC).</returns>
DateTimeOffset.AddDays(days: float) : DateTimeOffset
type IApplicationBuilder = member Build: unit -> RequestDelegate member New: unit -> IApplicationBuilder member Use: middleware: Func<RequestDelegate,RequestDelegate> -> IApplicationBuilder member ApplicationServices: IServiceProvider member Properties: IDictionary<string,obj> member ServerFeatures: IFeatureCollection
<summary> Defines a class that provides the mechanisms to configure an application's request pipeline. </summary>
(extension) IApplicationBuilder.Run(handler: AspNetCore.Http.RequestDelegate) : unit