Skip to content

Instantly share code, notes, and snippets.

@bvanderveen
Created March 21, 2011 09:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bvanderveen/879240 to your computer and use it in GitHub Desktop.
Save bvanderveen/879240 to your computer and use it in GitHub Desktop.
Untested sketch of Kayak support in Gate.
using System;
using System.Collections.Generic;
using Kayak.Http;
// utterly, completely, maximally untested sketch of an OWIN-Kayak adapter.
namespace Gate.Kayak
{
using Application =
Action<
IDictionary<string, object>,
Action<
string,
IDictionary<string, string>,
Func<
// on next
Func<
ArraySegment<byte>, // data
Action, // continuation
bool // continuation was or will be invoked
>,
// on error
Action<Exception>,
// on complete
Action,
// cancel
Action
>
>,
Action<Exception>
>;
public static class KayakExtensions
{
public static IDisposable RunApp(this IHttpServer server, Application app)
{
return new OwinResponder(server, app);
}
public class OwinResponder : IDisposable
{
IHttpServer server;
Application app;
public OwinResponder(IHttpServer server, Application app)
{
this.server = server;
server.OnRequest += new EventHandler<HttpRequestEventArgs>(server_OnRequest);
this.app = app;
}
public void Dispose()
{
server.OnRequest -= server_OnRequest;
server = null;
app = null;
}
void server_OnRequest(object sender, HttpRequestEventArgs e)
{
var request = e.Request;
var response = e.Response;
var env = new Dictionary<string, object>(StringComparer.InvariantCultureIgnoreCase);
env.SetRequestScheme("http");
env.SetRequestMethod(request.Method);
string[] qSplit = null;
var path = request.Uri.Contains("?") ? (qSplit = request.Uri.Split('?'))[0] : request.Uri;
if (qSplit != null)
env.SetRequestQueryString(qSplit[1]);
env.SetRequestPath(request.Uri);
env.SetRequestPathBase("");
env.SetRequestHeaders(request.Headers);
var requestBody = new BodyDelegate(request, response);
env.SetRequestBody(requestBody.Subscribe);
app(env, (status, headers, body) =>
{
response.WriteHeaders(status, headers);
body(
(data, continuation) => {
return response.WriteBody(data, continuation);
},
error =>
{
response.End();
},
() =>
{
response.End();
});
},
error =>
{
response.End();
});
}
class BodyDelegate
{
IRequest req;
IResponse res;
Func<ArraySegment<byte>, Action, bool> next;
Action<Exception> error;
Action complete;
public BodyDelegate(IRequest req, IResponse res)
{
this.req = req;
this.res = res;
}
public Action Subscribe(
Func<ArraySegment<byte>, Action, bool> next,
Action<Exception> error,
Action complete)
{
if (req.GetIsContinueExpected())
res.WriteContinue();
this.next = next;
this.error = error;
this.complete = complete;
req.OnBody += new EventHandler<global::Kayak.DataEventArgs>(req_OnBody);
req.OnEnd += new EventHandler(req_OnEnd);
return () =>
{
this.next = null;
this.error = null;
this.complete = null;
this.req = null;
this.res = null;
req.OnBody -= new EventHandler<global::Kayak.DataEventArgs>(req_OnBody);
req.OnEnd -= new EventHandler(req_OnEnd);
};
}
void req_OnEnd(object sender, EventArgs e)
{
complete();
}
void req_OnBody(object sender, global::Kayak.DataEventArgs e)
{
e.WillInvokeContinuation = next(e.Data, e.Continuation);
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment