This document defines a standard interface between .NET web servers and web applications. The goal of the OWIN interface is to decouple server and application, encourage the development of simple "middleware" modules for .NET web development, and, by being an open standard, stimulate the open source ecosystem of .NET web development tools.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
The OWIN interface is expressed as a single raw .NET delegate (the application delegate).
Action<
// an environment dictionary containing server and request data
IDictionary<string, object>,
// response callback
Action<string, IDictionary<string, string>, IEnumerable<object>>,
// error callback
Action<Exception>
>
In this document, an OWIN-compatible web server is referred to as a "host", and an instance of the above delegate is referred to as an "application". Broadly speaking, hosts invoke applications (providing as arguments an environment dictionary, and response and error callbacks), and the application either provides a response to the host by invoking the response callback with response information, or indicates an error by invoking the error callback with an exception. How an application is provided to a host is outside the scope of this specification and must be documented by the host implementor.
Because OWIN is defined in terms of a raw delegate, there is no need for an assembly called "OWIN.dll" or similar. Implementing either the host or application side the OWIN spec does not introduce a dependency to a project.
An application delegate takes an environment, a response callback, and an error callback. When an application delegate is invoked, it must invoke either the response callback or the error callback exactly once, or throw an exception. A callback provided to an application by a host must not throw an exception.
When a host invokes an application delegate, it provides an environment dictionary which represents the request the application is to process. The environment dictionary also provides additional context to the application. An environment dictionary must be mutable and must contain the following keys whose values must be non-null unless otherwise specified below:
owin.RequestMethod |
The HTTP request method string of the request (e.g., "GET", "POST"). |
owin.RequestUri |
The HTTP request URI string of the request. The value includes the query string of the HTTP request URI (e.g., "/path/and?query=string"). The URI must be relative to the application delegate; see Paths. |
owin.RequestHeaders
|
A dictionary of the form The dictionary must be mutable and its keys must be case-insensitive. Keys must be HTTP header names without The requirements below are predicated on RFC 2616 section 4.2. Values must be |
owin.RequestBody
|
A delegate of the form In response to an invocation of the request body delegate, the host must invoke either the result callback or the exception callback exactly once. When invoking the result callback, a host must provide an |
owin.BaseUri
|
The portion of the request URI's path corresponding to the "root" of the application object. See Paths. |
owin.ServerName, owin.ServerPort
|
Hosts should provide values which can be used to reconstruct the full URI of the request in absence of the HTTP Host header of the request.
|
owin.UriScheme
|
"http" or "https".
|
owin.RemoteEndPoint
|
A System.Net.IPEndPoint representing the connected client.
|
owin.Version
|
The string "1.0" indicating OWIN version 1.0.
|
In addition to these keys, the host, application, or user may add arbitrary data associated with the request to the environment dictionary.
The response callback of the application delegate takes three arguments of type string, Dictionary<string, string>, and IEnumerable<object>>. These arguments together represent an HTTP response generated by an application.
The first argument to the response callback must be a string which contains the integer status of the response followed by a space and a reason phrase without a newline (e.g., "200 OK"). All characters in the status string provided by an application should be within the ASCII codepage.
The second argument to the response callback must be a dictionary representing the headers to be sent with the request (the response header dictionary). The dictionary must be mutable and its keys must be case-insensitive. The keys must be header field-names without ':' or whitespace. Values must be string objects containing the corresponding header field-value strings. The application must encode or strip all '\r' and '\n' characters from header value data. The application must use the token "\r\n" to delimit values that are required to be sent as separate response headers of the same name (this is to support Set-Cookie). Applications must not generate response header dictionaries whose values start or end with "\r\n", contain adjacent "\r\n" delimiters, or are null, empty, or consist entirely of linear whitespace (as defined by RFC 2616 section 2.2). All characters in header field-name and field-value strings should be within the ASCII codepage.
The third argument to the response callback must be a instance of IEnumerable<object> which represents the body data (the response enumerable), or null if the response does not include a body. Each item in the response enumerable may be of one of the following types (the response item types):
byte[]ArraySegment<byte>FileInfoAction<Action<object>,Action<Exception>>Hosts must write both byte[] and ArraySegment<byte> to the underlying transport as raw data. FileInfo must cause the host to write the named file to the underlying transport. How relative file paths are resolved is outside the scope of this specification and must be documented by the host implementor.
An item of the type Action<Action<object>,Action<Exception>> (an asynchronous response delegate) allows applications to provide the next item asynchronously. The semantics of this delegate are the same as that of the application delegate and the request body delegate. The host must provide non-null result and exception callbacks to the delegate, and when the delegate is invoked, the application must invoke either the result or exception callback exactly once. A host must invoke an asynchronous response delegate exactly once, and the callbacks it provides must not throw exceptions. The application may invoke the result callback with objects of any of the response item types.
In the interest of extensibility, a response enumerable may contain items (and an asynchronous response delegate may yield values) whose types are not among the response item types listed above, and hosts may support additional response item types and define and document corresponding behaviors. If a host does not recognize the type of an object contained in the response enumerable or yielded by an asynchronous response delegate, it may ignore the object and continue enumerating.
Hosts must enumerate the enumerable to completion (i.e., until MoveNext returns false) or until an exception is thrown by MoveNext() or the Current property. After all of the items have been enumerated or if an exception occurs during enumeration, the host must call Dispose on the enumerator.
Hosts may have the ability to map application objects to some base path. For example, a host might have an application delegate configured to respond to requests beginning with "/my-app", in which case it must set the value of "owin.BaseUri" in the environment dictionary to "/my-app". If this host receives a request for "/my-app/foo", the owin.RequestUri value of the environment dictionary provided to the application configured to respond at "/my-app" must be "/foo". The value of "owin.BaseUri" may be an empty string and must not end with a trailing slash; the value of the "owin.RequestUri" property must not be an empty string and must start with a slash.
An application might generate an exception in the following places:
GetEnumerator method of the response enumerable.MoveNext method of the enumerator returned by the response enumerable.Current property of the enumerator returned by the response enumerable.An application should attempt to trap its own internal errors and generate an appropriate (possibly 500-level) response rather than propagating an exception up to the host.
After an application provides a response, if the response enumerable is non-null, the host should attempt to enumerate at least one item from the response enumerable before writing the response headers to the underlying transport. If the enumeration of the first item results in an error, the host will be able to generate a 500-level response. Otherwise, the application has caught as many of its internal errors as possible and host can begin the response without further buffering. If an exception is thrown by the application while enumerating subsequent items from the response body enumerable, the host may write a textual description of the error to the underlying transport, and/or close the connection.
A host might generate exceptions in the following places:
An exception generated in either of these places may indicate that the client has closed or dropped the connection, or another transport-layer error has occurred. The application should perform any post-mortem logic it needs to, and must propagate the exception back to the host through one of the sites described in Application Errors.
This specification draws heavily on the wonderful PEP 333 (WSGI). Many thanks to everyone participating in the discussion at .NET HTTP Abstractions, and in particular: