Created
March 21, 2011 09:57
-
-
Save bvanderveen/879240 to your computer and use it in GitHub Desktop.
Untested sketch of Kayak support in Gate.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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