Update 429 retry-after response handling (#1305)

* Always check the response headers when a 429 response is returned from OneDrive, so that the 'retry-after' value is correctly consumed and used
This commit is contained in:
abraunegg 2021-03-03 11:12:27 +11:00 committed by GitHub
parent 1078795d6f
commit 81e40ba76d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -979,6 +979,8 @@ final class OneDriveApi
try { try {
// try and catch any curl error // try and catch any curl error
http.perform(); http.perform();
// Check the HTTP Response headers - needed for correct 429 handling
// check will be performed in checkHttpCode()
writeln(); writeln();
// Reset onProgress to not display anything for next download done using exit scope // Reset onProgress to not display anything for next download done using exit scope
} catch (CurlException e) { } catch (CurlException e) {
@ -991,12 +993,14 @@ final class OneDriveApi
try { try {
// try and catch any curl error // try and catch any curl error
http.perform(); http.perform();
// Check the HTTP Response headers - needed for correct 429 handling
// check will be performed in checkHttpCode()
} catch (CurlException e) { } catch (CurlException e) {
displayOneDriveErrorMessage(e.msg, getFunctionName!({})); displayOneDriveErrorMessage(e.msg, getFunctionName!({}));
} }
} }
// Check the HTTP response code // Check the HTTP response code, which, if a 429, will also check response headers
checkHttpCode(); checkHttpCode();
} }
@ -1029,6 +1033,7 @@ final class OneDriveApi
http.url = url; http.url = url;
addAccessTokenHeader(); addAccessTokenHeader();
auto response = perform(postData); auto response = perform(postData);
// Check the HTTP response code, which, if a 429, will also check response headers
checkHttpCode(); checkHttpCode();
return response; return response;
} }
@ -1105,19 +1110,8 @@ final class OneDriveApi
try { try {
http.perform(); http.perform();
// Get the HTTP Response headers - needed for correct 429 handling // Check the HTTP Response headers - needed for correct 429 handling
auto responseHeaders = http.responseHeaders(); checkHTTPResponseHeaders();
// HTTP Server Response Headers Debugging if --https-debug is being used
if (.debugResponse){
log.vdebug("onedrive.perform() => HTTP Response Headers: ", responseHeaders);
}
// is retry-after in the response headers
if ("retry-after" in http.responseHeaders) {
// Set the retry-after value
log.vdebug("onedrive.perform() => Received a 'Retry-After' Header Response with the following value: ", http.responseHeaders["retry-after"]);
log.vdebug("onedrive.perform() => Setting retryAfterValue to: ", http.responseHeaders["retry-after"]);
.retryAfterValue = to!ulong(http.responseHeaders["retry-after"]);
}
} catch (CurlException e) { } catch (CurlException e) {
// Parse and display error message received from OneDrive // Parse and display error message received from OneDrive
log.vdebug("onedrive.perform() Generated a OneDrive CurlException"); log.vdebug("onedrive.perform() Generated a OneDrive CurlException");
@ -1150,6 +1144,8 @@ final class OneDriveApi
} }
try { try {
http.perform(); http.perform();
// Check the HTTP Response headers - needed for correct 429 handling
checkHTTPResponseHeaders();
// no error from http.perform() on re-try // no error from http.perform() on re-try
log.log("Internet connectivity to Microsoft OneDrive service has been restored"); log.log("Internet connectivity to Microsoft OneDrive service has been restored");
retrySuccess = true; retrySuccess = true;
@ -1187,6 +1183,23 @@ final class OneDriveApi
} }
return json; return json;
} }
private void checkHTTPResponseHeaders()
{
// Get the HTTP Response headers - needed for correct 429 handling
auto responseHeaders = http.responseHeaders();
if (.debugResponse){
log.vdebug("http.perform() => HTTP Response Headers: ", responseHeaders);
}
// is retry-after in the response headers
if ("retry-after" in http.responseHeaders) {
// Set the retry-after value
log.vdebug("http.perform() => Received a 'Retry-After' Header Response with the following value: ", http.responseHeaders["retry-after"]);
log.vdebug("http.perform() => Setting retryAfterValue to: ", http.responseHeaders["retry-after"]);
.retryAfterValue = to!ulong(http.responseHeaders["retry-after"]);
}
}
private void checkHttpCode() private void checkHttpCode()
{ {
@ -1303,10 +1316,12 @@ final class OneDriveApi
// 429 - Too Many Requests // 429 - Too Many Requests
case 429: case 429:
// Too many requests in a certain time window // Too many requests in a certain time window
// Check the HTTP Response headers - needed for correct 429 handling
checkHTTPResponseHeaders();
// https://docs.microsoft.com/en-us/sharepoint/dev/general-development/how-to-avoid-getting-throttled-or-blocked-in-sharepoint-online // https://docs.microsoft.com/en-us/sharepoint/dev/general-development/how-to-avoid-getting-throttled-or-blocked-in-sharepoint-online
log.vlog("OneDrive returned a 'HTTP 429 - Too Many Requests' - gracefully handling error"); log.vlog("OneDrive returned a 'HTTP 429 - Too Many Requests' - gracefully handling error");
throw new OneDriveException(http.statusLine.code, http.statusLine.reason); throw new OneDriveException(http.statusLine.code, http.statusLine.reason);
// Server side (OneDrive) Errors // Server side (OneDrive) Errors
// 500 - Internal Server Error // 500 - Internal Server Error
// 502 - Bad Gateway // 502 - Bad Gateway