async Task<object> ExecuteOperation(ILightNodeOptions options, OperationContext context)
{
// prepare
var handler = this;
var httpContext = context.Context;
var methodParameters = (object[])context.Parameters;
bool isVoid = true;
object result = null;
switch (handler.handlerBodyType)
{
case HandlerBodyType.Action:
handler.methodActionBody(httpContext, methodParameters);
break;
case HandlerBodyType.Func:
isVoid = false;
result = handler.methodFuncBody(httpContext, methodParameters);
break;
case HandlerBodyType.AsyncAction:
var actionTask = handler.methodAsyncActionBody(httpContext, methodParameters);
await actionTask.ConfigureAwait(false);
break;
case HandlerBodyType.AsyncFunc:
isVoid = false;
var funcTask = handler.methodAsyncFuncBody(httpContext, methodParameters);
await funcTask.ConfigureAwait(false);
var extractor = taskResultExtractors[FindTaskType(funcTask.GetType())];
result = extractor(funcTask);
break;
default:
throw new InvalidOperationException("critical:register code is broken");
}
if (!isVoid)
{
// append header
var responseHeader = httpContext.Response.Headers;
var encoding = context.ContentFormatter.Encoding;
responseHeader["Content-Type"] = context.ContentFormatter.MediaType + ((encoding == null) ? "" : "; charset=" + encoding.WebName);
if (!string.IsNullOrWhiteSpace(context.ContentFormatter.ContentEncoding))
{
responseHeader["Content-Encoding"] = context.ContentFormatter.ContentEncoding;
}
httpContext.EmitOK();
var responseStream = httpContext.Response.Body;
if (options.StreamWriteOption == StreamWriteOption.DirectWrite)
{
context.ContentFormatter.Serialize(new UnclosableStream(responseStream), result);
}
else
{
using (var buffer = new MemoryStream())
{
context.ContentFormatter.Serialize(new UnclosableStream(buffer), result);
responseHeader["Content-Length"] = buffer.Position.ToString();
buffer.Position = 0;
if (options.StreamWriteOption == StreamWriteOption.BufferAndWrite)
{
buffer.CopyTo(responseStream); // not CopyToAsync
}
else
{
await buffer.CopyToAsync(responseStream).ConfigureAwait(false);
}
}
}
return result;
}
else
{
httpContext.EmitNoContent();
return null;
}
}