Open Web Interface for .NET (OWIN)
-------------------------------------------------------------------------
Running OWIN middleware in the ASP.NET pipeline
"dependencies": {
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
"Microsoft.AspNetCore.Owin": "1.0.0"
},
public Task OwinHello(IDictionary<string, object> environment)
{
string responseText = "Hello World via OWIN";
byte[] responseBytes = Encoding.UTF8.GetBytes(responseText);
// OWIN Environment Keys: http://owin.org/spec/spec/owin-1.0.0.html
var responseStream = (Stream)environment["owin.ResponseBody"];
var responseHeaders = (IDictionary<string, string[]>)environment["owin.ResponseHeaders"];
responseHeaders["Content-Length"] = new string[] { responseBytes.Length.ToString(CultureInfo.InvariantCulture) };
responseHeaders["Content-Type"] = new string[] { "text/plain" };
return responseStream.WriteAsync(responseBytes, 0, responseBytes.Length);
}
public void Configure(IApplicationBuilder app)
{
app.UseOwin(pipeline =>
{
pipeline(next => OwinHello);
});
}
app.UseOwin(pipeline =>
{
pipeline(next =>
{
// do something before
return OwinHello;
// do something after
});
});
-------------------------------------------------------------------------------------------------
Using ASP.NET Hosting on an OWIN-based server
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Owin;
using Microsoft.Extensions.Options;
using Nowin;
namespace NowinSample
{
public class NowinServer : IServer
{
private INowinServer _nowinServer;
private ServerBuilder _builder;
public IFeatureCollection Features { get; } = new FeatureCollection();
public NowinServer(IOptions<ServerBuilder> options)
{
Features.Set<IServerAddressesFeature>(new ServerAddressesFeature());
_builder = options.Value;
}
public void Start<TContext>(IHttpApplication<TContext> application)
{
// Note that this example does not take into account of Nowin's "server.OnSendingHeaders" callback.
// Ideally we should ensure this method is fired before disposing the context.
Func<IDictionary<string, object>, Task> appFunc = async env =>
{
// The reason for 2 level of wrapping is because the OwinFeatureCollection isn't mutable
// so features can't be added
var features = new FeatureCollection(new OwinFeatureCollection(env));
var context = application.CreateContext(features);
try
{
await application.ProcessRequestAsync(context);
}
catch (Exception ex)
{
application.DisposeContext(context, ex);
throw;
}
application.DisposeContext(context, null);
};
// Add the web socket adapter so we can turn OWIN websockets into ASP.NET Core compatible web sockets.
// The calling pattern is a bit different
appFunc = OwinWebSocketAcceptAdapter.AdaptWebSockets(appFunc);
// Get the server addresses
var address = Features.Get<IServerAddressesFeature>().Addresses.First();
var uri = new Uri(address);
var port = uri.Port;
IPAddress ip;
if (!IPAddress.TryParse(uri.Host, out ip))
{
ip = IPAddress.Loopback;
}
_nowinServer = _builder.SetAddress(ip)
.SetPort(port)
.SetOwinApp(appFunc)
.Build();
_nowinServer.Start();
}
public void Dispose()
{
_nowinServer?.Dispose();
}
}
}
using System;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.Extensions.DependencyInjection;
using Nowin;
using NowinSample;
namespace Microsoft.AspNetCore.Hosting
{
public static class NowinWebHostBuilderExtensions
{
public static IWebHostBuilder UseNowin(this IWebHostBuilder builder)
{
return builder.ConfigureServices(services =>
{
services.AddSingleton<IServer, NowinServer>();
});
}
public static IWebHostBuilder UseNowin(this IWebHostBuilder builder, Action<ServerBuilder> configure)
{
builder.ConfigureServices(services =>
{
services.Configure(configure);
});
return builder.UseNowin();
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
namespace NowinSample
{
public class Program
{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseNowin()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run();
}
}
}
------------------------------------------------------------------------------
Run ASP.NET Core on an OWIN-based server and use its WebSockets support
public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
if (context.WebSockets.IsWebSocketRequest)
{
WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
await EchoWebSocket(webSocket);
}
else
{
await next();
}
});
app.Run(context =>
{
return context.Response.WriteAsync("Hello World");
});
}
private async Task EchoWebSocket(WebSocket webSocket)
{
byte[] buffer = new byte[1024];
WebSocketReceiveResult received = await webSocket.ReceiveAsync(
new ArraySegment<byte>(buffer), CancellationToken.None);
while (!webSocket.CloseStatus.HasValue)
{
// Echo anything we receive
await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, received.Count),
received.MessageType, received.EndOfMessage, CancellationToken.None);
received = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer),
CancellationToken.None);
}
await webSocket.CloseAsync(webSocket.CloseStatus.Value,
webSocket.CloseStatusDescription, CancellationToken.None);
}
}
}
------------------------------------------------------------------------------------------------
OWIN keys
Request Data (OWIN v1.0.0)
Key Value (type) Description
owin.RequestScheme String
owin.RequestMethod String
owin.RequestPathBase String
owin.RequestPath String
owin.RequestQueryString String
owin.RequestProtocol String
owin.RequestHeaders IDictionary<string,string[]>
owin.RequestBody Stream
Request Data (OWIN v1.1.0)
Key Value (type) Description
owin.RequestId String Optional
Response Data (OWIN v1.0.0)
Key Value (type) Description
owin.ResponseStatusCode int Optional
owin.ResponseReasonPhrase String Optional
owin.ResponseHeaders IDictionary<string,string[]>
owin.ResponseBody Stream
Other Data (OWIN v1.0.0)
Key Value (type) Description
owin.CallCancelled CancellationToken
owin.Version String
Common Keys
Key Value (type) Description
ssl.ClientCertificate X509Certificate
ssl.LoadClientCertAsync Func<Task>
server.RemoteIpAddress String
server.RemotePort String
server.LocalIpAddress String
server.LocalPort String
server.IsLocal bool
server.OnSendingHeaders Action<Action<object>,object>
SendFiles v0.3.0
Key Value (type) Description
sendfile.SendAsync See delegate signature Per Request
Opaque v0.3.0
Key Value (type) Description
opaque.Version String
opaque.Upgrade OpaqueUpgrade See delegate signature
opaque.Stream Stream
opaque.CallCancelled CancellationToken
WebSocket v0.3.0
Key Value (type) Description
websocket.Version String
websocket.Accept WebSocketAccept See delegate signature.
websocket.AcceptAlt Non-spec
websocket.SubProtocol String See RFC6455 Section 4.2.2 Step 5.5
websocket.SendAsync WebSocketSendAsync See delegate signature.
websocket.ReceiveAsync WebSocketReceiveAsync See delegate signature.
websocket.CloseAsync WebSocketCloseAsync See delegate signature.
websocket.CallCancelled CancellationToken
websocket.ClientCloseStatus int Optional
websocket.ClientCloseDescription String Optional