private Task<IClientResponse> ProcessRequest(string httpMethod, string url, Action<IClientRequest> prepareRequest, IDictionary<string, string> postData, bool disableWrites = false) { if (url == null) { throw new ArgumentNullException("url"); } if (prepareRequest == null) { throw new ArgumentNullException("prepareRequest"); } if (_appFunc == null) { throw new InvalidOperationException(); } if (_shutDownToken.IsCancellationRequested) { return TaskAsyncHelper.FromError<IClientResponse>(new InvalidOperationException("Service unavailable")); } var tcs = new TaskCompletionSource<IClientResponse>(); var clientTokenSource = new SafeCancellationTokenSource(); var env = new Dictionary<string, object>(); // Server specific setup env[OwinConstants.Version] = "1.0"; // Request specific setup var uri = new Uri(url); env[OwinConstants.RequestProtocol] = "HTTP/1.1"; env[OwinConstants.CallCancelled] = clientTokenSource.Token; env[OwinConstants.RequestMethod] = httpMethod; env[OwinConstants.RequestPathBase] = String.Empty; env[OwinConstants.RequestPath] = uri.LocalPath; env[OwinConstants.RequestQueryString] = uri.Query.Length > 0 ? uri.Query.Substring(1) : String.Empty; env[OwinConstants.RequestScheme] = uri.Scheme; env[OwinConstants.RequestBody] = GetRequestBody(postData); var headers = new Dictionary<string, string[]>(); env[OwinConstants.RequestHeaders] = headers; headers.SetHeader("X-Server", "MemoryHost"); headers.SetHeader("X-Server-Name", InstanceName); if (httpMethod == "POST") { headers.SetHeader("Content-Type", "application/x-www-form-urlencoded"); } // Run the client function to initialize the request prepareRequest(new Request(env, clientTokenSource.Cancel)); var networkObservable = new NetworkObservable(disableWrites); var clientStream = new ClientStream(networkObservable); var serverStream = new ServerStream(networkObservable); var response = new Response(clientStream); // Trigger the tcs on flush. This mimicks the client side networkObservable.OnFlush = () => tcs.TrySetResult(response); // Cancel the network observable on cancellation of the token clientTokenSource.Token.Register(networkObservable.Cancel); env[OwinConstants.ResponseBody] = serverStream; env[OwinConstants.ResponseHeaders] = new Dictionary<string, string[]>(); _appFunc(env).ContinueWith(task => { object statusCode; if (env.TryGetValue(OwinConstants.ResponseStatusCode, out statusCode) && (int)statusCode == 403) { tcs.TrySetException(new InvalidOperationException("Forbidden")); } else if (task.IsFaulted) { tcs.TrySetException(task.Exception.InnerExceptions); } else if (task.IsCanceled) { tcs.TrySetCanceled(); } else { tcs.TrySetResult(response); } // Close the server stream when the request has ended serverStream.Close(); clientTokenSource.Dispose(); }); return tcs.Task; }
private Task <IClientResponse> ProcessRequest(string httpMethod, string url, Action <IClientRequest> prepareRequest, IDictionary <string, string> postData, bool disableWrites = false) { if (url == null) { throw new ArgumentNullException("url"); } if (prepareRequest == null) { throw new ArgumentNullException("prepareRequest"); } if (_appFunc == null) { throw new InvalidOperationException(); } if (_shutDownToken.IsCancellationRequested) { return(TaskAsyncHelper.FromError <IClientResponse>(new InvalidOperationException("Service unavailable"))); } var tcs = new TaskCompletionSource <IClientResponse>(); var clientTokenSource = new SafeCancellationTokenSource(); var env = new Dictionary <string, object>(); // Server specific setup env[OwinConstants.Version] = "1.0"; // Request specific setup var uri = new Uri(url); env[OwinConstants.RequestProtocol] = "HTTP/1.1"; env[OwinConstants.CallCancelled] = clientTokenSource.Token; env[OwinConstants.RequestMethod] = httpMethod; env[OwinConstants.RequestPathBase] = String.Empty; env[OwinConstants.RequestPath] = uri.LocalPath; env[OwinConstants.RequestQueryString] = uri.Query.Length > 0 ? uri.Query.Substring(1) : String.Empty; env[OwinConstants.RequestScheme] = uri.Scheme; env[OwinConstants.RequestBody] = GetRequestBody(postData); var headers = new Dictionary <string, string[]>(); env[OwinConstants.RequestHeaders] = headers; headers.SetHeader("X-Server", "MemoryHost"); headers.SetHeader("X-Server-Name", InstanceName); if (httpMethod == "POST") { headers.SetHeader("Content-Type", "application/x-www-form-urlencoded"); } // Run the client function to initialize the request prepareRequest(new Request(env, clientTokenSource.Cancel)); var networkObservable = new NetworkObservable(disableWrites); var clientStream = new ClientStream(networkObservable); var serverStream = new ServerStream(networkObservable); var response = new Response(clientStream); // Trigger the tcs on flush. This mimicks the client side networkObservable.OnFlush = () => tcs.TrySetResult(response); // Cancel the network observable on cancellation of the token clientTokenSource.Token.Register(networkObservable.Cancel); env[OwinConstants.ResponseBody] = serverStream; env[OwinConstants.ResponseHeaders] = new Dictionary <string, string[]>(); _appFunc(env).ContinueWith(task => { object statusCode; if (env.TryGetValue(OwinConstants.ResponseStatusCode, out statusCode) && (int)statusCode == 403) { tcs.TrySetException(new InvalidOperationException("Forbidden")); } else if (task.IsFaulted) { tcs.TrySetException(task.Exception.InnerExceptions); } else if (task.IsCanceled) { tcs.TrySetCanceled(); } else { tcs.TrySetResult(response); } // Close the server stream when the request has ended serverStream.Close(); clientTokenSource.Dispose(); }); return(tcs.Task); }
public Response(ClientStream stream) { _stream = stream; }