private async Task <WebClientResult> RetryableRequest(Func <Task <string> > makeRequest, int retryCount)
        {
            var webClientResult = new WebClientResult();

            for (var attempt = 0; attempt < retryCount; attempt++)
            {
                try
                {
                    if (attempt > 0)
                    {
                        webClientResult.DebugInfo
                            = webClientResult.DebugInfo.AppendLine("retrying...");
                    }
                    webClientResult.Content = await makeRequest();

                    webClientResult.DebugInfo
                        = webClientResult.DebugInfo.AppendLine("Complete");
                    webClientResult.Success = true;
                    return(webClientResult);
                }
                catch (WebException e)
                {
                    var responseStream = e.Response?.GetResponseStream();
                    if (responseStream != null)
                    {
                        using (var resp = new StreamReader(responseStream))
                        {
                            webClientResult.DebugInfo
                                = webClientResult.DebugInfo.AppendLine(resp.ReadToEnd());
                            _logger.LogError(webClientResult.DebugInfo);
                        }
                    }
                    else
                    {
                        webClientResult.DebugInfo
                            = webClientResult.DebugInfo.AppendLine($"{e.Message}");
                        _logger.LogError(webClientResult.DebugInfo);
                    }
                }
                catch (Exception e)
                {
                    webClientResult.DebugInfo
                        = webClientResult.DebugInfo.AppendLine($"{e.Message}");
                    _logger.LogError(webClientResult.DebugInfo);
                }

                await Task.Delay(1000);
            }

            webClientResult.DebugInfo
                = webClientResult.DebugInfo.AppendLine("Failed");
            _logger.LogError(webClientResult.DebugInfo);
            return(webClientResult);
        }
        public void Intercept(IInvocation invocation)
        {
            var webAttribs = from s in
                                 (from a in invocation.Method.GetCustomAttributes(false).ToArray() select a)
                             where s is WebInvokeAttribute || s is WebGetAttribute
                             select s;

            if (webAttribs.Count() != 1)
                throw new Exception("ServiceModel.Web attributes not found on method");

            var attrib = webAttribs.Single();

            var uriTemplate = new UriTemplate("");
            string httpMethod = "GET";

            if (attrib is WebGetAttribute)
            {
                uriTemplate = new UriTemplate(((WebGetAttribute)attrib).UriTemplate);
                httpMethod = "GET";
            }
            else if (attrib is WebInvokeAttribute)
            {
                uriTemplate = new UriTemplate(((WebInvokeAttribute)attrib).UriTemplate);
                httpMethod = "POST";
            }

            var uriParams = new Dictionary<string, string>();

            ParameterInfo[] Params = invocation.Method.GetParameters();
            object[] args = invocation.Arguments;

            for (int i = 0; i < invocation.Arguments.Count(); i++)
            {
                string sValue = TypeUtils.StringOrNull(args[i]);
                if (!string.IsNullOrEmpty(sValue)) uriParams.Add(Params[i].Name, sValue);
            }

            var combinedUriParams = _baseParams.Union(uriParams).ToDictionary(p => p.Key, p => p.Value);

            Uri uriLoc = uriTemplate.BindByName(_uriBase, combinedUriParams, false);
            //swReflection.Stop();
            Log.Trace(uriLoc.ToString());

            var swSetup = new Stopwatch();
            swSetup.Start();

            _webRequest = (HttpWebRequest)WebRequest.Create(uriLoc);

            // Add OAuth authorization header
            if (_oAuthParams != null)
            {
                var oAuthUtils = new OAuthUtils();

                string authHeader = (oAuthUtils.GetAuthorizationHeader(
                    System.Web.HttpUtility.UrlDecode(uriLoc.AbsoluteUri), _oAuthParams.Realm, _oAuthParams.ConsumerKey, _oAuthParams.ConsumerSecret,
                    _oAuthParams.UserToken, _oAuthParams.UserSecret, null, SignatureMethod.HMACSHA1, httpMethod)).ToString();

                _webRequest.Headers[HttpRequestHeader.Authorization] = authHeader;
            }

            Log.Trace(_webRequest.Headers.ToString());

            //TODO replace with app settings
            _webRequest.UserAgent = "Toketee 0.1";
            _webRequest.Timeout = _timeout;
            _webRequest.KeepAlive = false;
            _webRequest.Method = httpMethod;
            swSetup.Stop();
            //TODO implement connection manager

            var swRequest = new Stopwatch();
            swRequest.Start();

            try
            {
                _webResponse = (HttpWebResponse)_webRequest.GetResponse();
            }
            catch (WebException we)
            {
                switch (we.Status)
                {
                    case WebExceptionStatus.Timeout:
                        // retry operation, see if endpoint is available or if there's another problem
                        break;

                }
                _webResponse = (HttpWebResponse)we.Response;
            }
            finally
            {

            }
            swRequest.Stop();

            Encoding encode = System.Text.Encoding.UTF8;

            if (_webResponse != null)
            {
                var responseStream = new StreamReader(_webResponse.GetResponseStream(), encode);
                string sResponse = responseStream.ReadToEnd();

                LogJson.Trace(new JsonFormatter(sResponse).Format());

                // TODO add exception trapping
                var result = new WebClientResult(_webResponse, sResponse, true, null);

                // TODO move to an error handling method
                // This is twitter specific, need to move over to TwitterAPI
                switch (Utility.Parse.GetValueFromJson(sResponse, "error"))
                {
                    case "Incorrect signature":
                        throw new OAuthIncorrectSignatureException(sResponse);
                }
                invocation.ReturnValue = result;
            }
            else
            {
                invocation.ReturnValue = null;
            }
        }
        public void Intercept(IInvocation invocation)
        {
            var webAttribs = from s in
                                 (from a in invocation.Method.GetCustomAttributes(false).ToArray() select a)
                             where s is WebInvokeAttribute || s is WebGetAttribute
                             select s;

            if (webAttribs.Count() != 1)
                throw new Exception("ServiceModel.Web attributes not found on method");

            var attrib = webAttribs.Single();

            UriTemplate uriTemplate = new UriTemplate("");
            string httpMethod = "GET";
            if (attrib is WebGetAttribute)
            {
                uriTemplate = new UriTemplate(((WebGetAttribute)attrib).UriTemplate);
                httpMethod = "GET";
            }
            else if (attrib is WebInvokeAttribute)
            {
                uriTemplate = new UriTemplate(((WebInvokeAttribute)attrib).UriTemplate);
                httpMethod = "POST";
            }

            Dictionary<string, string> uriParams = new Dictionary<string, string>();

            ParameterInfo[] Params = invocation.Method.GetParameters();
            object[] Args = invocation.Arguments;
            string sValue;
            for (int i = 0; i < invocation.Arguments.Count(); i++)
            {
                sValue = TypeUtils.StringOrNull(Args[i]);
                if (!string.IsNullOrEmpty(sValue)) uriParams.Add(Params[i].Name, sValue);
            }

            Uri uri = uriTemplate.BindByName(new Uri("http://api.twitter.com"), uriParams, false);
            //swReflection.Stop();
            logger.Trace(uri.ToString());

            Stopwatch swSetup = new Stopwatch();
            swSetup.Start();

            webRequest = (HttpWebRequest)WebRequest.Create(uri);

            // Add OAuth authorization header
            if (OAuthParams != null)
            {
                OAuthUtils oAuthUtils = new OAuthUtils();

                string authHeader = (oAuthUtils.GetAuthorizationHeader(
                    System.Web.HttpUtility.UrlDecode(uri.AbsoluteUri), OAuthParams.Realm, OAuthParams.ConsumerKey, OAuthParams.ConsumerSecret,
                    OAuthParams.UserToken, OAuthParams.UserSecret, null, SignatureMethod.HMACSHA1, httpMethod)).ToString();

                webRequest.Headers[HttpRequestHeader.Authorization] = authHeader;
            }

            logger.Trace(webRequest.Headers.ToString());

            webRequest.UserAgent = "Toketee 0.1";
            webRequest.Timeout = Timeout;
            webRequest.KeepAlive = false;
            webRequest.Method = httpMethod;
            swSetup.Stop();
            //TODO implement connection manager
            //webRequest.ServicePoint
            var swRequest = new Stopwatch();
            swRequest.Start();

            try
            {
                webResponse = (HttpWebResponse)webRequest.GetResponse();
            }
            catch (WebException we)
            {
                switch (we.Status)
                {
                    case WebExceptionStatus.Timeout:
                        // retry operation, see if endpoint is available or if there's another problem
                        break;

                }
                webResponse = (HttpWebResponse)we.Response;
            }
            finally
            {

            }
            swRequest.Stop();

            Encoding encode = System.Text.Encoding.UTF8;

            var responseStream = new StreamReader(webResponse.GetResponseStream(), encode);
            string sResponse = responseStream.ReadToEnd();

            logJson.Trace(new JsonFormatter(sResponse).Format());

            // TODO add exception trapping
            var result = new WebClientResult(webResponse, sResponse, true, null);

            // TODO move to an error handling method
            // Look for known Twitter return errors
            var jObject = new JObject(sResponse);
            switch (jObject["error"].ToString())
            {
                case "Incorrect signature":
                    throw new TwitterOAuthIncorrectSignatureException(sResponse);
            }

            invocation.ReturnValue = result;
        }