예제 #1
0
        public async Task <IBoxResponse <T> > ExecuteAsync <T>(IBoxRequest request)
            where T : class
        {
            // Need to account for special cases when the return type is a stream
            bool isStream                 = typeof(T) == typeof(Stream);
            var  retryCounter             = 0;
            ExponentialBackoff expBackoff = new ExponentialBackoff();

            try
            {
                // TODO: yhu@ better handling of different request
                var isMultiPartRequest = request.GetType() == typeof(BoxMultiPartRequest);
                var isBinaryRequest    = request.GetType() == typeof(BoxBinaryRequest);

                while (true)
                {
                    HttpRequestMessage httpRequest = getHttpRequest(request, isMultiPartRequest, isBinaryRequest);
                    Debug.WriteLine(string.Format("RequestUri: {0}", httpRequest.RequestUri));
                    HttpResponseMessage response = await getResponse(request, isStream, httpRequest).ConfigureAwait(false);

                    //need to wait for Retry-After seconds and then retry request
                    var retryAfterHeader = response.Headers.RetryAfter;

                    // If we get a retryable/transient error code and this is not a multi part request (meaning a file upload, which cannot be retried
                    // because the stream cannot be reset) and we haven't exceeded the number of allowed retries, then retry the request.
                    // If we get a 202 code and has a retry-after header, we will retry after
                    if (!isMultiPartRequest &&
                        (response.StatusCode == TooManyRequests
                         ||
                         response.StatusCode == HttpStatusCode.InternalServerError
                         ||
                         response.StatusCode == HttpStatusCode.BadGateway
                         ||
                         response.StatusCode == HttpStatusCode.ServiceUnavailable
                         ||
                         response.StatusCode == HttpStatusCode.GatewayTimeout
                         ||
                         (response.StatusCode == HttpStatusCode.Accepted && retryAfterHeader != null)) &&
                        retryCounter++ < RetryLimit)
                    {
                        TimeSpan delay = expBackoff.GetRetryTimeout(retryCounter);

                        Debug.WriteLine("HttpCode : {0}. Waiting for {1} seconds to retry request. RequestUri: {2}", response.StatusCode, delay.Seconds, httpRequest.RequestUri);

                        await Task.Delay(delay);
                    }
                    else
                    {
                        BoxResponse <T> boxResponse = await getBoxResponse <T>(isStream, response).ConfigureAwait(false);

                        return(boxResponse);
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(string.Format("Exception: {0}", ex.Message));
                throw;
            }
        }
예제 #2
0
        public async Task <IBoxResponse <T> > ExecuteAsyncWithoutRetry <T>(IBoxRequest request)
            where T : class
        {
            // Need to account for special cases when the return type is a stream
            bool isStream = typeof(T) == typeof(Stream);

            try
            {
                // TODO: yhu@ better handling of different request
                var isMultiPartRequest = request.GetType() == typeof(BoxMultiPartRequest);
                var isBinaryRequest    = request.GetType() == typeof(BoxBinaryRequest);

                HttpRequestMessage httpRequest = getHttpRequest(request, isMultiPartRequest, isBinaryRequest);
                Debug.WriteLine(string.Format("RequestUri: {0}", httpRequest.RequestUri));
                HttpResponseMessage response = await getResponse(request, isStream, httpRequest).ConfigureAwait(false);

                BoxResponse <T> boxResponse = await getBoxResponse <T>(isStream, response).ConfigureAwait(false);

                return(boxResponse);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(string.Format("Exception: {0}", ex.Message));
                throw;
            }
        }
예제 #3
0
        public async Task <IBoxResponse <T> > ExecuteAsync <T>(IBoxRequest request)
            where T : class
        {
            // Need to account for special cases when the return type is a stream
            bool isStream = typeof(T) == typeof(Stream);

            HttpRequestMessage httpRequest = request.GetType() == typeof(BoxMultiPartRequest) ?
                                             BuildMultiPartRequest(request as BoxMultiPartRequest) :
                                             BuildRequest(request);

            // Add headers
            foreach (var kvp in request.HttpHeaders)
            {
                if (kvp.Key == Constants.RequestParameters.ContentMD5)
                {
                    httpRequest.Content.Headers.Add(kvp.Key, kvp.Value);
                }
                else
                {
                    httpRequest.Headers.TryAddWithoutValidation(kvp.Key, kvp.Value);
                }
            }


            // If we are retrieving a stream, we should return without reading the entire response
            HttpCompletionOption completionOption = isStream ?
                                                    HttpCompletionOption.ResponseHeadersRead :
                                                    HttpCompletionOption.ResponseContentRead;

            Debug.WriteLine(string.Format("RequestUri: {0}", httpRequest.RequestUri));//, RequestHeader: {1} , httpRequest.Headers.Select(i => string.Format("{0}:{1}", i.Key, i.Value)).Aggregate((i, j) => i + "," + j)));

            try
            {
                HttpClient client = CreateClient(request);

                HttpResponseMessage response = await client.SendAsync(httpRequest, completionOption).ConfigureAwait(false);

                BoxResponse <T> boxResponse = new BoxResponse <T>();
                boxResponse.Headers = response.Headers;

                // Translate the status codes that interest us
                boxResponse.StatusCode = response.StatusCode;
                switch (response.StatusCode)
                {
                case HttpStatusCode.OK:
                case HttpStatusCode.Created:
                case HttpStatusCode.NoContent:
                case HttpStatusCode.Found:
                    boxResponse.Status = ResponseStatus.Success;
                    break;

                case HttpStatusCode.Accepted:
                    boxResponse.Status = ResponseStatus.Pending;
                    break;

                case HttpStatusCode.Unauthorized:
                    boxResponse.Status = ResponseStatus.Unauthorized;
                    break;

                case HttpStatusCode.Forbidden:
                    boxResponse.Status = ResponseStatus.Forbidden;
                    break;

                default:
                    boxResponse.Status = ResponseStatus.Error;
                    break;
                }

                if (isStream && boxResponse.Status == ResponseStatus.Success)
                {
                    var resObj = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);

                    boxResponse.ResponseObject = resObj as T;
                }
                else
                {
                    boxResponse.ContentString = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                }
                return(boxResponse);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(string.Format("Exception: {0}", ex.Message));
                throw;
            }
        }
        public async Task <IBoxResponse <T> > ExecuteAsync <T>(IBoxRequest request)
            where T : class
        {
            // Need to account for special cases when the return type is a stream
            bool isStream                 = typeof(T) == typeof(Stream);
            var  retryCounter             = 0;
            ExponentialBackoff expBackoff = new ExponentialBackoff();

            try
            {
                // TODO: yhu@ better handling of different request
                var isMultiPartRequest = request.GetType() == typeof(BoxMultiPartRequest);
                var isBinaryRequest    = request.GetType() == typeof(BoxBinaryRequest);

                while (true)
                {
                    HttpRequestMessage httpRequest = null;

                    if (isMultiPartRequest)
                    {
                        httpRequest = BuildMultiPartRequest(request as BoxMultiPartRequest);
                    }
                    else if (isBinaryRequest)
                    {
                        httpRequest = BuildBinaryRequest(request as BoxBinaryRequest);
                    }
                    else
                    {
                        httpRequest = BuildRequest(request);
                    }

                    // Add headers
                    foreach (var kvp in request.HttpHeaders)
                    {
                        // They could not be added to the headers directly
                        if (kvp.Key == Constants.RequestParameters.ContentMD5 ||
                            kvp.Key == Constants.RequestParameters.ContentRange)
                        {
                            httpRequest.Content.Headers.Add(kvp.Key, kvp.Value);
                        }
                        else
                        {
                            httpRequest.Headers.TryAddWithoutValidation(kvp.Key, kvp.Value);
                        }
                    }

                    // If we are retrieving a stream, we should return without reading the entire response
                    HttpCompletionOption completionOption = isStream ?
                                                            HttpCompletionOption.ResponseHeadersRead :
                                                            HttpCompletionOption.ResponseContentRead;

                    Debug.WriteLine(string.Format("RequestUri: {0}", httpRequest.RequestUri));

                    HttpClient client = GetClient(request);

                    // Not disposing the reponse since it will affect stream response
                    var response = await client.SendAsync(httpRequest, completionOption).ConfigureAwait(false);

                    //need to wait for Retry-After seconds and then retry request
                    var retryAfterHeader = response.Headers.RetryAfter;

                    // If we get a retryable/transient error code and this is not a multi part request (meaning a file upload, which cannot be retried
                    // because the stream cannot be reset) and we haven't exceeded the number of allowed retries, then retry the request.
                    // If we get a 202 code and has a retry-after header, we will retry after
                    if (!isMultiPartRequest &&
                        (response.StatusCode == TooManyRequests
                         ||
                         response.StatusCode == HttpStatusCode.InternalServerError
                         ||
                         response.StatusCode == HttpStatusCode.GatewayTimeout
                         ||
                         response.StatusCode == HttpStatusCode.BadGateway
                         ||
                         (response.StatusCode == HttpStatusCode.Accepted && retryAfterHeader != null)) &&
                        retryCounter++ < RetryLimit)
                    {
                        TimeSpan delay = expBackoff.GetRetryTimeout(retryCounter);

                        Debug.WriteLine("HttpCode : {0}. Waiting for {1} seconds to retry request. RequestUri: {2}", response.StatusCode, delay.Seconds, httpRequest.RequestUri);

                        await Task.Delay(delay);
                    }
                    else
                    {
                        BoxResponse <T> boxResponse = new BoxResponse <T>();
                        boxResponse.Headers = response.Headers;

                        // Translate the status codes that interest us
                        boxResponse.StatusCode = response.StatusCode;
                        switch (response.StatusCode)
                        {
                        case HttpStatusCode.OK:
                        case HttpStatusCode.Created:
                        case HttpStatusCode.NoContent:
                        case HttpStatusCode.Found:
                        case HttpStatusCode.PartialContent:     // Download with range
                            boxResponse.Status = ResponseStatus.Success;
                            break;

                        case HttpStatusCode.Accepted:
                            boxResponse.Status = ResponseStatus.Pending;
                            break;

                        case HttpStatusCode.Unauthorized:
                            boxResponse.Status = ResponseStatus.Unauthorized;
                            break;

                        case HttpStatusCode.Forbidden:
                            boxResponse.Status = ResponseStatus.Forbidden;
                            break;

                        case TooManyRequests:
                            boxResponse.Status = ResponseStatus.TooManyRequests;
                            break;

                        default:
                            boxResponse.Status = ResponseStatus.Error;
                            break;
                        }

                        if (isStream && boxResponse.Status == ResponseStatus.Success)
                        {
                            var resObj = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);

                            boxResponse.ResponseObject = resObj as T;
                        }
                        else
                        {
                            boxResponse.ContentString = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

                            // We can safely dispose the response now since all of it has been read
                            response.Dispose();
                        }

                        return(boxResponse);
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(string.Format("Exception: {0}", ex.Message));
                throw;
            }
        }
        public async Task <IBoxResponse <T> > ExecuteAsync <T>(IBoxRequest request)
            where T : class
        {
            // Need to account for special cases when the return type is a stream
            bool isStream   = typeof(T) == typeof(Stream);
            var  numRetries = 3;

            try
            {
                // TODO: yhu@ better handling of different request
                var isMultiPartRequest = request.GetType() == typeof(BoxMultiPartRequest);
                var isBinaryRequest    = request.GetType() == typeof(BoxBinaryRequest);

                while (true)
                {
                    HttpRequestMessage httpRequest = null;

                    if (isMultiPartRequest)
                    {
                        httpRequest = BuildMultiPartRequest(request as BoxMultiPartRequest);
                    }
                    else if (isBinaryRequest)
                    {
                        httpRequest = BuildBinaryRequest(request as BoxBinaryRequest);
                    }
                    else
                    {
                        httpRequest = BuildRequest(request);
                    }

                    // Add headers
                    foreach (var kvp in request.HttpHeaders)
                    {
                        // They could not be added to the headers directly
                        if (kvp.Key == Constants.RequestParameters.ContentMD5 ||
                            kvp.Key == Constants.RequestParameters.ContentRange)
                        {
                            httpRequest.Content.Headers.Add(kvp.Key, kvp.Value);
                        }
                        else
                        {
                            httpRequest.Headers.TryAddWithoutValidation(kvp.Key, kvp.Value);
                        }
                    }

                    // If we are retrieving a stream, we should return without reading the entire response
                    HttpCompletionOption completionOption = isStream ?
                                                            HttpCompletionOption.ResponseHeadersRead :
                                                            HttpCompletionOption.ResponseContentRead;

                    Debug.WriteLine(string.Format("RequestUri: {0}", httpRequest.RequestUri));//, RequestHeader: {1} , httpRequest.Headers.Select(i => string.Format("{0}:{1}", i.Key, i.Value)).Aggregate((i, j) => i + "," + j)));

                    HttpClient client = GetClient(request);

                    // Not disposing the reponse since it will affect stream response
                    var response = await client.SendAsync(httpRequest, completionOption).ConfigureAwait(false);

                    //need to wait for Retry-After seconds and then retry request
                    var retryAfterHeader = response.Headers.RetryAfter;

                    // If we get a 429 error code and this is not a multi part request (meaning a file upload, which cannot be retried
                    // because the stream cannot be reset) and we haven't exceeded the number of allowed retries, then retry the request.
                    // If we get a 202 code and has a retry-after header, we will retry after
                    if (
                        ((response.StatusCode == TooManyRequests && !isMultiPartRequest)
                         ||
                         (response.StatusCode == HttpStatusCode.Accepted && retryAfterHeader != null)) &&
                        numRetries-- > 0)
                    {
                        TimeSpan delay = TimeSpan.FromSeconds(2);
                        if (retryAfterHeader.Delta.HasValue)
                        {
                            delay = retryAfterHeader.Delta.Value;
                        }

                        Debug.WriteLine("HttpCode : {0}. Waiting for {1} seconds to retry request. RequestUri: {2}", response.StatusCode, delay.Seconds, httpRequest.RequestUri);

                        await CrossPlatform.Delay(delay);
                    }
                    else
                    {
                        BoxResponse <T> boxResponse = new BoxResponse <T>();
                        boxResponse.Headers = response.Headers;

                        // Translate the status codes that interest us
                        boxResponse.StatusCode = response.StatusCode;
                        switch (response.StatusCode)
                        {
                        case HttpStatusCode.OK:
                        case HttpStatusCode.Created:
                        case HttpStatusCode.NoContent:
                        case HttpStatusCode.Found:
                            boxResponse.Status = ResponseStatus.Success;
                            break;

                        case HttpStatusCode.Accepted:
                            boxResponse.Status = ResponseStatus.Pending;
                            break;

                        case HttpStatusCode.Unauthorized:
                            boxResponse.Status = ResponseStatus.Unauthorized;
                            break;

                        case HttpStatusCode.Forbidden:
                            boxResponse.Status = ResponseStatus.Forbidden;
                            break;

                        case TooManyRequests:
                            boxResponse.Status = ResponseStatus.TooManyRequests;
                            break;

                        default:
                            boxResponse.Status = ResponseStatus.Error;
                            break;
                        }

                        if (isStream && boxResponse.Status == ResponseStatus.Success)
                        {
                            var resObj = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);

                            boxResponse.ResponseObject = resObj as T;
                        }
                        else
                        {
                            boxResponse.ContentString = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                        }

                        return(boxResponse);
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(string.Format("Exception: {0}", ex.Message));
                throw;
            }
        }
예제 #6
0
        public async Task <IBoxResponse <T> > ExecuteAsync <T>(IBoxRequest request)
            where T : class
        {
            // Need to account for special cases when the return type is a stream
            bool isStream   = typeof(T) == typeof(Stream);
            var  numRetries = 3;

            try
            {
                while (true)
                {
                    HttpRequestMessage httpRequest = request.GetType() == typeof(BoxMultiPartRequest) ?
                                                     BuildMultiPartRequest(request as BoxMultiPartRequest) :
                                                     BuildRequest(request);

                    // Add headers
                    foreach (var kvp in request.HttpHeaders)
                    {
                        if (kvp.Key == Constants.RequestParameters.ContentMD5)
                        {
                            httpRequest.Content.Headers.Add(kvp.Key, kvp.Value);
                        }
                        else
                        {
                            httpRequest.Headers.TryAddWithoutValidation(kvp.Key, kvp.Value);
                        }
                    }

                    // If we are retrieving a stream, we should return without reading the entire response
                    HttpCompletionOption completionOption = isStream ?
                                                            HttpCompletionOption.ResponseHeadersRead :
                                                            HttpCompletionOption.ResponseContentRead;

                    Debug.WriteLine(string.Format("RequestUri: {0}", httpRequest.RequestUri));//, RequestHeader: {1} , httpRequest.Headers.Select(i => string.Format("{0}:{1}", i.Key, i.Value)).Aggregate((i, j) => i + "," + j)));

                    HttpClient      client      = CreateClient(request);
                    BoxResponse <T> boxResponse = new BoxResponse <T>();

                    HttpResponseMessage response = await client.SendAsync(httpRequest, completionOption).ConfigureAwait(false);

                    if (response.StatusCode == TooManyRequests && numRetries-- > 0)
                    {
                        //need to wait for Retry-After seconds and then retry request
                        var retryAfterHeader = response.Headers.RetryAfter;

                        TimeSpan delay;
                        if (retryAfterHeader.Delta.HasValue)
                        {
                            delay = retryAfterHeader.Delta.Value;
                        }
                        else
                        {
                            delay = TimeSpan.FromMilliseconds(2000);
                        }

                        Debug.WriteLine("TooManyRequests error (429). Waiting for {0} seconds to retry request. RequestUri: {1}", delay.Seconds, httpRequest.RequestUri);

                        await CrossPlatform.Delay(Convert.ToInt32(delay.TotalMilliseconds));
                    }
                    else
                    {
                        boxResponse.Headers = response.Headers;

                        // Translate the status codes that interest us
                        boxResponse.StatusCode = response.StatusCode;
                        switch (response.StatusCode)
                        {
                        case HttpStatusCode.OK:
                        case HttpStatusCode.Created:
                        case HttpStatusCode.NoContent:
                        case HttpStatusCode.Found:
                            boxResponse.Status = ResponseStatus.Success;
                            break;

                        case HttpStatusCode.Accepted:
                            boxResponse.Status = ResponseStatus.Pending;
                            break;

                        case HttpStatusCode.Unauthorized:
                            boxResponse.Status = ResponseStatus.Unauthorized;
                            break;

                        case HttpStatusCode.Forbidden:
                            boxResponse.Status = ResponseStatus.Forbidden;
                            break;

                        case TooManyRequests:
                            boxResponse.Status = ResponseStatus.TooManyRequests;
                            break;

                        default:
                            boxResponse.Status = ResponseStatus.Error;
                            break;
                        }

                        if (isStream && boxResponse.Status == ResponseStatus.Success)
                        {
                            var resObj = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);

                            boxResponse.ResponseObject = resObj as T;
                        }
                        else
                        {
                            boxResponse.ContentString = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                        }

                        return(boxResponse);
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(string.Format("Exception: {0}", ex.Message));
                throw;
            }
        }