A Brief History of OWIN

Open Web Interface for .NET

Ryan Riley

Tachyus logo

Why OWIN?

Problem: Desire for Fast and Light-weight Frameworks and Servers

  • ASP.NET was "too heavy"
  • IIS was "too slow"

Solutions

Problem: Repetition

  • Sinatra clones
  • ASP.NET adapters
  • Self-host adapters (esp. HttpListener)

Solution: Collaborate

September 7, 2010

I’ve noticed a trend recently in projects each of us has worked/is working on and wondered if we might be willing to pool our resources....

...

If you are interested in working together, please let me know.... I’m sure we could agree on a common platform for our efforts.

September 27, 2010

Benjamin van der Veen proposed the first set of interfaces:

public interface IHttpResponder {
    IObservable<IHttpServerResponse> Respond(
        IHttpServerRequest request,
        IDictionary<string, object> context);
}

public interface IHttpServerRequest {
    HttpRequestLine RequestLine { get; }
    IDictionary<string, string> Headers { get; }
    IObservable<ArraySegment<byte>> GetBodyChunk();
}

public interface IHttpServerResponse {
    HttpStatusLine StatusLine { get; }
    IDictionary<string, string> Headers { get; }
    string BodyFile { get; }
    IObservable<ArraySegment<byte>> GetBodyChunk();
}

November 29, 2010

Scott Koon creates .NET HTTP Abstractions

https://groups.google.com/forum/#!forum/net-http-abstractions

Problem: Opinions and Existing Implementations

Solution: Define a Common Interface

Consensus to share server wrappers

Progress!

Name: Open Web Interface for .NET (OWIN)

Specification writing begins

BHAG: Run ASP.NET MVC on OWIN

Problem: Trouble in Paradise

Troublemakers

  • Object-oriented faction
  • Functional faction
  • Dynamic faction

Disagreement on library dependency

Disagreement on interface types

Solution : No Dependency Required

Solution : Use Delegates and FCL Types

What about the Iron- Languages?

IDictionary<string, object> to the rescue!

Problem: How to Represent Async Access to Message Body?

Proposed Solution #1: Stream

  • Rejected
  • Considered "too heavy"
  • Async access considered "too slow"

Proposed Solution #2: IObservable<T>

  • Rejected
  • Back-pressure a concern
  • Required library dependency for .NET 3.5

Proposed Solution #3: Task<T>

  • Rejected
  • Required .NET 4.0
  • Some libraries had existing .NET 3.5 base

Proposed Soluion #4: "Delegate of Doom"

Accepted!

public delegate void AppDelegate(
    IDictionary<string, object> env,
    ResultDelegate result,
    Action<Exception> fault);

public delegate void ResultDelegate(
    string status,
    IDictionary<string, IEnumerable<string>> headers,
    BodyDelegate body);

public delegate void BodyDelegate(
    Func<ArraySegment<byte>, bool> write,
    Func<Action, bool> flush,
    Action<Exception> end,
    CancellationToken cancellationToken);

Problem: Implementations Cease

"Delegate of Doom" proved too difficult for most

Solution: Gate Helper Library

???

When your library dependency becomes a helper dependency

from The Reality of a Developer's Life - in GIFs, Of Course

WIN!

SignalR

Problem: "Delegate of Doom" doesn't work for SignalR

Double-tap

  • Nancy
  • OWIN
  • Rack
  • Web API

Single-tap

  • ASP.NET MVC
  • Fubu MVC
  • node.js
  • Razor
  • SignalR

Explained

There are ways to run a single-tap web framework on a double-tap owin pipeline, but they all boil down to buffering write data.... Increased complexity, more memory to hold the body until the fwk returns, and cpu spent copying that data… Plus for fully synchronous web frameworks it means every response body will be entirely buffered because there’s no way for the server to deliver the output stream until the initial call returns. ... it’s pretty extreme compared to just passing the server’s output stream and a response header idictionary in the original call.

Explained (cont)

Running a double-tap framework on a single-tap pipeline by comparison is easy – the adapter just calls framework then calls its callback with the output stream.

Solution

using AppFunc = Func<IDitionary<string, object>, Task>

Task?

Push to 1.0

Microsoft adopts OWIN as Katana

New Implementations

owin.dll

Specified type aliases removed, but IAppBuilder remains:

public interface IAppBuilder
{
    IDictionary<string, object> Properties { get; }
    IAppBuilder Use(object middleware, params object[] args);
    object Build(Type returnType);
    IAppBuilder New();
}

Adoption!

Implementations

Katana (Microsoft.Owin)

Fix

Dyfrig

Frameworks

SignalR

NancyFx

ASP.NET Web API

FubuMVC

Simple.Web

Servers

System.Web

HttpListener

IIS

Nowin

Fracture

Middleware

CORS

Security

Routing (Superscribe)

Diagnostics

Glimpse v2.0

Put it All Together!

public class Startup {
    public void Configuration(IAppBuilder app) {
        app.Properties["host.AppName"] = "composed app";
        app.UseCors(Cors.CorsOptions.AllowAll)
           .UseWebApi(new HttpConfiguration())
           .MapHubs("signalr", new HubConfiguration())
           .UseNancy();
    }
}

Looking Ahead

ASP.NET vNext

BHAG Unlocked!

MVC 6

Assembly Neutral Interfaces

Time to revisit interface?

Faster Servers!

  • Kestrel
  • WebListener
  • Helios (IIS without System.Web)

OWIN Management Committee

Specification Updates

Join Us!

http://owin.org

http://github.com/owin/owin

http://groups.google.com/group/net-http-abstractions

A Brief History of OWIN

(Abridged)

A Sing Along

  • Key changes noted at bottom (verse n and chorus)
  • Don't sing words in parentheses

To the Tune of "Escape"

(with apologies to Rupert Holmes)

I was tired of my Web Forms

and thought Sinatra was cool

(verse 1)

I wrote my own library

then found that others had, too

So I wrote a quick email

and asked to collaborate

September 7, 2010

I’ve noticed a trend recently in projects each of us has worked/is working on and wondered if we might be willing to pool our resources....

...

If you are interested in working together, please let me know.... I’m sure we could agree on a common platform for our efforts.

And within only the first month

Ben proposed interfaces:

September 27, 2010

public interface IHttpResponder {
    IObservable<IHttpServerResponse> Respond(
        IHttpServerRequest request,
        IDictionary<string, object> context);
}

public interface IHttpServerRequest {
    HttpRequestLine RequestLine { get; }
    IDictionary<string, string> Headers { get; }
    IObservable<ArraySegment<byte>> GetBodyChunk();
}

public interface IHttpServerResponse {
    HttpStatusLine StatusLine { get; }
    IDictionary<string, string> Headers { get; }
    string BodyFile { get; }
    IObservable<ArraySegment<byte>> GetBodyChunk();
}

And then we ran into problems:

more people and opinions

(chorus)

We worked out all the conflicts,

choosing a protocol (approach)

(Just like the cool kids)

We bought the OWIN domain name

and started writing the specs

And set an audacious goal:

MVC on OWIN

We were blocked by factions:

  • OO (object-oriented)
  • FP (functional)
  • Dynamic

(verse 2)

Existing implementations

didn't want dependencies

We used only delegates,

and only FCL types

And for dynamic languages?

IDictionary<string, object>

But how to represent async?

We had a longer debate

(chorus)

Streams were considered "too heavy";

IObservable<T> too new

Task required a framework version

above .NET 4.0

So in the end we adopted

the "Delegate of Doom"

public delegate void AppDelegate(
    IDictionary<string, object> env,
    ResultDelegate result,
    Action<Exception> fault);

public delegate void ResultDelegate(
    string status,
    IDictionary<string, IEnumerable<string>> headers,
    BodyDelegate body);

public delegate void BodyDelegate(
    Func<ArraySegment<byte>, bool> write,
    Func<Action, bool> flush,
    Action<Exception> end,
    CancellationToken cancellationToken);

We finally had a solution,

along with many problems

(verse 3)

Where before we had prototypes;

now we had only the spec

Devs had trouble with DoD,

so Ben and Lou built Gate

But what nobody noticed

Gate was a (helper) dependency!

When your library dependency becomes a helper dependency

from The Reality of a Developer's Life - in GIFs, Of Course

Then along came SignalR

We tried to claim victory

(chorus)

We only had one problem:

"Delegate of Doom" didn't work

We went back to the drawing board:

Single- or double-tap?

Double-tap

  • Nancy
  • OWIN
  • Rack
  • Web API

Single-tap

  • ASP.NET MVC
  • Fubu MVC
  • node.js
  • Razor
  • SignalR

Explained

There are ways to run a single-tap web framework on a double-tap owin pipeline, but they all boil down to buffering write data.... Increased complexity, more memory to hold the body until the fwk returns, and cpu spent copying that data… Plus for fully synchronous web frameworks it means every response body will be entirely buffered because there’s no way for the server to deliver the output stream until the initial call returns. ... it’s pretty extreme compared to just passing the server’s output stream and a response header idictionary in the original call.

Explained (cont)

Running a double-tap framework on a single-tap pipeline by comparison is easy – the adapter just calls framework then calls its callback with the output stream.

And proposed a solution,

a simple delegate:

using AppFunc = Func<IDitionary<string, object>, Task>

Task?

Now we had real users

and started gaining traction

(verse 4)

We knew its name in an instant;

we knew the F5 experience

It was our old friend ASP.NET,

and we said, "Ah! It's you"

Then we laughed for a moment,

and we said, "We never knew ..."

That you would unlock our big goal

with MVC6

(chorus)

And build the Kestrel web server

that could run on Linux and Mac

If you like writing middleware pipelines

with .Use and .Map extensions,

Then you're the framework
we've looked for

let's go build new web apps!

One more time?

OWIN Management Committee

Specification Updates

Join Us!

http://owin.org

http://github.com/owin/owin

http://groups.google.com/group/net-http-abstractions