Skip to content

Commit

Permalink
Merge pull request #276 from box/upload-rate-limit-handling-fix
Browse files Browse the repository at this point in the history
fix so request is not retried for a 429 (rate limit) error on file up…
  • Loading branch information
cburnette authored Jan 19, 2017
2 parents e5e2a41 + e8f3e77 commit 5236b0d
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 12 deletions.
6 changes: 6 additions & 0 deletions Box.V2/Exceptions/BoxException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http.Headers;
using System.Text;

namespace Box.V2.Exceptions
Expand Down Expand Up @@ -47,6 +48,11 @@ public BoxException(string message, BoxError error) : base(message)
/// Error parsed from the message returned by the API
/// </summary>
public BoxError Error { get; set; }

/// <summary>
/// Response headers returned by the API
/// </summary>
public HttpResponseHeaders ResponseHeaders { get; set; }
}


Expand Down
14 changes: 7 additions & 7 deletions Box.V2/Extensions/BoxResponseExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,16 @@ public static IBoxResponse<T> ParseResults<T>(this IBoxResponse<T> response, IBo
if (errorMsg != null)
{
var err = new BoxError() { Code = response.StatusCode.ToString(), Description = "Forbidden", Message = errorMsg.ToString() };
throw new BoxException(err.Message, err);
throw new BoxException(err.Message, err) { StatusCode = response.StatusCode, ResponseHeaders = response.Headers };
}
else if (!string.IsNullOrWhiteSpace(response.ContentString))
{
response.Error = converter.Parse<BoxError>(response.ContentString);
throw new BoxException(response.ContentString, response.Error) {StatusCode = response.StatusCode};
throw new BoxException(response.ContentString, response.Error) { StatusCode = response.StatusCode, ResponseHeaders = response.Headers };
}
else
{
throw new BoxException("Forbidden");
throw new BoxException("Forbidden") { StatusCode = response.StatusCode, ResponseHeaders = response.Headers };
}
default:
if (!string.IsNullOrWhiteSpace(response.ContentString))
Expand All @@ -61,11 +61,11 @@ public static IBoxResponse<T> ParseResults<T>(this IBoxResponse<T> response, IBo
if (response is IBoxResponse<BoxPreflightCheck>)
{
BoxPreflightCheckConflictError<BoxFile> err = converter.Parse<BoxPreflightCheckConflictError<BoxFile>>(response.ContentString);
exToThrow = new BoxPreflightCheckConflictException<BoxFile>(response.ContentString, err);
exToThrow = new BoxPreflightCheckConflictException<BoxFile>(response.ContentString, err) { StatusCode = response.StatusCode, ResponseHeaders = response.Headers };
} else
{
BoxConflictError<T> error = converter.Parse<BoxConflictError<T>>(response.ContentString);
exToThrow = new BoxConflictException<T>(response.ContentString, error);
exToThrow = new BoxConflictException<T>(response.ContentString, error) { StatusCode = response.StatusCode, ResponseHeaders = response.Headers };
}

break;
Expand All @@ -80,10 +80,10 @@ public static IBoxResponse<T> ParseResults<T>(this IBoxResponse<T> response, IBo
}

throw exToThrow == null ?
new BoxException(response.ContentString, response.Error) { StatusCode = response.StatusCode } :
new BoxException(response.ContentString, response.Error) { StatusCode = response.StatusCode, ResponseHeaders = response.Headers } :
exToThrow;
}
throw new BoxException(response.ContentString) { StatusCode = response.StatusCode };
throw new BoxException(response.ContentString) { StatusCode = response.StatusCode, ResponseHeaders = response.Headers };
}
return response;
}
Expand Down
14 changes: 9 additions & 5 deletions Box.V2/Request/HttpRequestHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ public async Task<IBoxResponse<T>> ExecuteAsync<T>(IBoxRequest request)

try
{
while(true)
var isMultiPartRequest = request.GetType() == typeof(BoxMultiPartRequest);

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

// Add headers
foreach (var kvp in request.HttpHeaders)
Expand All @@ -55,7 +57,9 @@ public async Task<IBoxResponse<T>> ExecuteAsync<T>(IBoxRequest request)

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

if(response.StatusCode == TooManyRequests && numRetries-- > 0)
// 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((response.StatusCode == TooManyRequests && !isMultiPartRequest) && numRetries-- > 0)
{
//need to wait for Retry-After seconds and then retry request
var retryAfterHeader = response.Headers.RetryAfter;
Expand Down

0 comments on commit 5236b0d

Please sign in to comment.