Example #1
0
        public Task<IClientResponse> ProcessRequest(string url, Action<IClientRequest> prepareRequest, IDictionary<string, string> postData, bool disableWrites)
        {
            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.CallCancelled] = clientTokenSource.Token;
            string method = postData == null ? "GET" : "POST";
            env[OwinConstants.RequestMethod] = method;
            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;

            if (method == "POST")
            {
                headers.SetHeader("Content-Type", "application/x-www-form-urlencoded");
            }

            // Run the client function to initialize the request
            prepareRequest(new Request(env, clientTokenSource.Cancel));

            Response response = null;
            response = new Response(disableWrites, () => tcs.TrySetResult(response));
            env[OwinConstants.ResponseBody] = response.GetResponseStream();
            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);
                }

                response.Close();
                clientTokenSource.Dispose();
            });

            return tcs.Task;
        }
Example #2
0
        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;
        }