Beispiel #1
0
        public async Task <T> Run <T>(BizwebRequestMessage baseReqMsg,
                                      ExecuteRequestAsync <T> executeRequestAsync)
        {
            var tryCount = 0;

Start:
            try
            {
                using (var reqMsg = baseReqMsg.Clone())
                {
                    tryCount++;
                    return((await executeRequestAsync(reqMsg)).Result);
                }
            }
            catch (ApiRateLimitException)
            {
                if (tryCount >= MAX_RETRY)
                {
                    throw;
                }
                await Task.Delay(RETRY_DELAY);

                goto Start;
            }
        }
Beispiel #2
0
        /// <summary>
        /// Executes a request and returns the raw result string. Throws an exception when the response is invalid.
        /// </summary>
        public static async Task <string> ExecuteRequestToStringAsync(BizwebRequestMessage requestMsg,
                                                                      IRequestExecutionPolicy execPolicy)
        {
            if (requestMsg.Content != null)
            {
                //necessary to buffer content for multiple reads
                await requestMsg.Content.LoadIntoBufferAsync();
            }

            return(await execPolicy.Run(requestMsg, async (reqMsg) =>
            {
                //Need to create a RequestInfo before send RequestMessage
                //because after that, HttpClient will dispose RequestMessage
                var requestInfo = await CreateRequestSimpleInfoAsync(reqMsg);

                using (var response = await HttpUtils.SendHttpRequestAsync(reqMsg))
                {
                    //Check for and throw exception when necessary.
                    await CheckResponseExceptionsAsync(response, requestInfo);

                    var rawResponse = await response.Content.ReadAsStringAsync();
                    return new RequestResult <string>(response, rawResponse);
                }
            }));
        }
Beispiel #3
0
        /// <summary>
        /// Executes a request and returns the JToken result. Throws an exception when the response is invalid.
        /// </summary>
        public static async Task <JToken> ExecuteRequestAsync(BizwebRequestMessage requestMsg,
                                                              IRequestExecutionPolicy execPolicy)
        {
            if (requestMsg.Content != null)
            {
                //necessary to buffer content for multiple reads
                await requestMsg.Content.LoadIntoBufferAsync();
            }

            return(await execPolicy.Run(requestMsg, async (reqMsg) =>
            {
                //Need to create a RequestInfo before send RequestMessage
                //because after that, HttpClient will dispose RequestMessage
                var requestInfo = await CreateRequestSimpleInfoAsync(reqMsg);

                using (var response = await HttpUtils.SendHttpRequestAsync(reqMsg))
                {
                    //Check for and throw exception when necessary.
                    await CheckResponseExceptionsAsync(response, requestInfo);

                    // When using JToken make sure that dates are not stripped of any timezone information
                    // if tokens are de-serialised into strings/DateTime/DateTimeZoneOffset
                    using (var reader = new JsonTextReader(new StreamReader(await response.Content.ReadAsStreamAsync()))
                    {
                        DateParseHandling = DateParseHandling.None
                    })
                    {
                        //Notice: deserialize can fails when response body null or empty
                        var result = Deserialize(reader, reqMsg.RootElement);
                        return new RequestResult <JToken>(response, result);
                    }
                }
            }));
        }
Beispiel #4
0
        public async Task <T> Run <T>(BizwebRequestMessage baseReqMsg,
                                      ExecuteRequestAsync <T> executeRequestAsync)
        {
            var         accessToken = GetAccessToken(baseReqMsg);
            LeakyBucket bucket      = null;

            if (accessToken != null)
            {
                bucket = LeakyBucket.GetBucketByToken(accessToken);
            }

            while (true)
            {
                using (var reqMsg = baseReqMsg.Clone())
                {
                    if (accessToken != null)
                    {
                        await bucket.GrantAsync();
                    }

                    try
                    {
                        var fullResult = await executeRequestAsync(reqMsg);

                        var bucketState       = GetBucketState(fullResult.Response);
                        var reportedFillLevel = bucketState.Item1;
                        var reportedCapacity  = bucketState.Item2;

                        if (reportedFillLevel != null && reportedCapacity != null)
                        {
                            bucket?.SetBucketState(reportedFillLevel.Value, reportedCapacity.Value);
                        }

                        return(fullResult.Result);
                    }
                    catch (BizwebSharpException)
                    {
                        //An exception may still occur:
                        //-Shopify may have a slightly different algorithm
                        //-Shopify may change to a different algorithm in the future
                        //-There may be timing and latency delays
                        //-Multiple programs may use the same access token
                        //-Multiple instances of the same program may use the same access token
                        await Task.Delay(THROTTLE_DELAY);
                    }
                }
            }
        }
Beispiel #5
0
        /// <summary>
        /// Creates an <see cref="BizwebRequestMessage"/> by setting the method and the necessary authenticate information.
        /// </summary>
        /// <param name="authState">The Bizweb authenticate state.</param>
        /// <param name="pathAndQuery">The request's path.</param>
        /// <param name="method">The <see cref="HttpMethod"/> to use for the request.</param>
        /// <param name="content">The <see cref="HttpContent"/> to use for the request.</param>
        /// <param name="rootElement">The root element to deserialize. Default is null.</param>
        /// <returns>The prepared <see cref="BizwebRequestMessage"/>.</returns>
        public static BizwebRequestMessage CreateRequest(BizwebAuthorizationState authState,
                                                         string pathAndQuery, HttpMethod method, HttpContent content = null, string rootElement = null)
        {
            var baseUri     = BuildUri(authState.ApiUrl);
            var endPointUri = new Uri(baseUri, pathAndQuery);
            var msg         = new BizwebRequestMessage(endPointUri, method, content, rootElement);

            if (!string.IsNullOrEmpty(authState.AccessToken))
            {
                msg.Headers.Add(ApiConst.HEADER_KEY_ACCESS_TOKEN, authState.AccessToken);
                msg.Headers.Add("Cache-Control", "no-cache");
            }

            msg.Headers.Add("Accept", "application/json");

            return(msg);
        }
        public BizwebRequestMessage Clone()
        {
            var newContent = Content;

            if (newContent != null && newContent is JsonContent c)
            {
                newContent = c.Clone();
            }

            var cloned = new BizwebRequestMessage(RequestUri, Method, newContent, RootElement);

            // Copy over the request's headers which includes the access token if set
            foreach (var header in Headers)
            {
                cloned.Headers.Add(header.Key, header.Value);
            }

            return(cloned);
        }
        public async Task <T> Run <T>(BizwebRequestMessage baseReqMsg,
                                      ExecuteRequestAsync <T> executeRequestAsync)
        {
            while (true)
            {
                try
                {
                    using (var reqMsg = baseReqMsg.Clone())
                    {
                        var fullResult = await executeRequestAsync(reqMsg);

                        return(fullResult.Result);
                    }
                }
                catch (ApiRateLimitException)
                {
                    await Task.Delay(RETRY_DELAY);
                }
            }
        }
Beispiel #8
0
 /// <summary>
 /// Executes a request and returns the given type. Throws an exception when the response is invalid.
 /// Use this method when the expected response is a single line or simple object that doesn't warrant its own class.
 /// </summary>
 public static async Task <T> ExecuteRequestAsync <T>(BizwebRequestMessage requestMsg)
     where T : new()
 {
     return(await ExecuteRequestAsync <T>(requestMsg, DefaultRequestExecutionPolicy.Default));
 }
Beispiel #9
0
 /// <summary>
 /// Executes a request and returns the given type. Throws an exception when the response is invalid.
 /// Use this method when the expected response is a single line or simple object that doesn't warrant its own class.
 /// </summary>
 public static async Task <T> ExecuteRequestAsync <T>(BizwebRequestMessage requestMsg,
                                                      IRequestExecutionPolicy execPolicy)
     where T : new()
 {
     return((await ExecuteRequestAsync(requestMsg, execPolicy)).ToObject <T>());
 }
Beispiel #10
0
 /// <summary>
 /// Executes a request and returns the JToken result. Throws an exception when the response is invalid.
 /// </summary>
 public static async Task <JToken> ExecuteRequestAsync(BizwebRequestMessage requestMsg)
 {
     return(await ExecuteRequestAsync(requestMsg, DefaultRequestExecutionPolicy.Default));
 }
Beispiel #11
0
 /// <summary>
 /// Executes a request and returns the raw result string. Throws an exception when the response is invalid.
 /// </summary>
 public static async Task <string> ExecuteRequestToStringAsync(BizwebRequestMessage requestMsg)
 {
     return(await ExecuteRequestToStringAsync(requestMsg, DefaultRequestExecutionPolicy.Default));
 }
Beispiel #12
0
 public async Task <T> Run <T>(BizwebRequestMessage requestMsg,
                               ExecuteRequestAsync <T> executeRequestAsync)
 {
     return((await executeRequestAsync(requestMsg)).Result);
 }