Created
December 19, 2010 05:36
-
-
Save bvanderveen/747129 to your computer and use it in GitHub Desktop.
An IApplication which transforms requests/responses to/from a wrapped IApplication
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
// this snippet assumes the IAsyncResult implementation provided here: | |
// http://msdn.microsoft.com/en-us/magazine/cc163467.aspx | |
using System; | |
using Owin; | |
namespace TransformMiddleware | |
{ | |
// Defines a tranformation of an HTTP context. | |
public interface IHttpTransform | |
{ | |
// Transforms a request | |
IAsyncResult BeginTransformRequest(IRequest request, AsyncCallback callback, object state); | |
IRequest EndTransformRequest(IAsyncResult asyncResult); | |
// Transforms a response. Request is provided for context. Note that IApplication is not provided since it has no context. | |
IAsyncResult BeginTransformResponse(IRequest request, IResponse response, AsyncCallback callback, object state); | |
IResponse EndTransformResponse(IAsyncResult asyncResult); | |
} | |
// A middleware which uses IHttpTransform to transform requests and responses to and from a wrapped application. | |
public class TransformMiddleware : IApplication | |
{ | |
IApplication wrap; | |
IHttpTransform transform; | |
public TransformMiddleware(IApplication wrap, IHttpTransform transform) | |
{ | |
this.wrap = wrap; | |
this.transform = transform; | |
} | |
public IAsyncResult BeginInvoke(IRequest request, AsyncCallback callback, object state) | |
{ | |
var asyncResult = new AsyncResult<IResponse>(callback, state); | |
// 1. perform the request transform to obtain a new request. | |
transform.BeginTransformRequest(request, iasr => | |
{ | |
IRequest transformedRequest = null; | |
Exception transformRequestException = null; | |
try | |
{ | |
transformedRequest = transform.EndTransformRequest(iasr); | |
} | |
catch (Exception e) | |
{ | |
transformRequestException = e; | |
} | |
// if an error occurred, propagate it to our caller | |
if (transformRequestException != null) | |
asyncResult.SetAsCompleted(transformRequestException, iasr.CompletedSynchronously); | |
else | |
{ | |
// 2. provide the transformed request to the wrapped application, obtain the response. | |
wrap.BeginInvoke(transformedRequest, iasr2 => | |
{ | |
IResponse response = null; | |
Exception invokeException = null; | |
try | |
{ | |
response = wrap.EndInvoke(iasr2); | |
} | |
catch (Exception e) | |
{ | |
invokeException = e; | |
} | |
// again, if an error occurred, propagate it back to the original caller. | |
if (invokeException != null) | |
asyncResult.SetAsCompleted(invokeException, iasr2.CompletedSynchronously); | |
else | |
{ | |
// 3. transform the response. | |
transform.BeginTransformResponse(transformedRequest, response, iasr3 => | |
{ | |
IResponse transformedResponse = null; | |
Exception transformResponseException = null; | |
try | |
{ | |
transformedResponse = transform.EndTransformResponse(iasr3); | |
} | |
catch (Exception e) | |
{ | |
transformResponseException = e; | |
} | |
// propagate the error if any. | |
if (transformResponseException != null) | |
asyncResult.SetAsCompleted(transformResponseException, iasr3.CompletedSynchronously); | |
else | |
// 4. return the transformed response to the caller. | |
asyncResult.SetAsCompleted(transformedResponse, iasr3.CompletedSynchronously); | |
}, null); | |
} | |
}, null); | |
} | |
}, null); | |
return asyncResult; | |
} | |
public IResponse EndInvoke(IAsyncResult result) | |
{ | |
// takes care of waiting, throwing exceptions, etc. | |
return ((AsyncResult<IResponse>)result).EndInvoke(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment