completedWithoutRecoverableError = false;
redirectCount++;
wasRecentlyRedirected = true;
if (redirectCount > 5) {
throw new S3ServiceException("Encountered too many 307 Redirects, aborting request.");
}
} else if (responseCode == 500) {
// Retry on S3 Internal Server 500 errors.
completedWithoutRecoverableError = false;
sleepOnInternalError(++internalErrorCount);
} else {
completedWithoutRecoverableError = true;
}
String contentType = "";
if (httpMethod.getResponseHeader("Content-Type") != null) {
contentType = httpMethod.getResponseHeader("Content-Type").getValue();
}
log.debug("Response for '" + httpMethod.getPath()
+ "'. Content-Type: " + contentType
+ ", Headers: " + Arrays.asList(httpMethod.getResponseHeaders()));
// Check we received the expected result code.
if (responseCode != expectedResponseCode) {
log.warn("Response '" + httpMethod.getPath() + "' - Unexpected response code "
+ responseCode + ", expected " + expectedResponseCode);
if (Mimetypes.MIMETYPE_XML.equals(contentType)
&& httpMethod.getResponseBodyAsStream() != null
&& httpMethod.getResponseContentLength() != 0)
{
log.warn("Response '" + httpMethod.getPath()
+ "' - Received error response with XML message");
StringBuffer sb = new StringBuffer();
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(
new HttpMethodReleaseInputStream(httpMethod)));
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} finally {
if (reader != null) {
reader.close();
}
}
httpMethod.releaseConnection();
// Throw exception containing the XML message document.
S3ServiceException exception =
new S3ServiceException("S3 " + httpMethod.getName()
+ " failed for '" + httpMethod.getPath() + "'", sb.toString());
if ("RequestTimeout".equals(exception.getS3ErrorCode())) {
int retryMaxCount = Jets3tProperties
.getInstance(Constants.JETS3T_PROPERTIES_FILENAME)
.getIntProperty("httpclient.retry-max", 5);
if (requestTimeoutErrorCount < retryMaxCount) {
requestTimeoutErrorCount++;
log.warn("Response '" + httpMethod.getPath()
+ "' - Retrying connection that failed with RequestTimeout error"
+ ", attempt number " + requestTimeoutErrorCount + " of "
+ retryMaxCount);
completedWithoutRecoverableError = false;
} else {
log.warn("Response '" + httpMethod.getPath()
+ "' - Exceeded maximum number of retries for RequestTimeout errors: "
+ retryMaxCount);
throw exception;
}
} else if ("RequestTimeTooSkewed".equals(exception.getS3ErrorCode())) {
long timeDifferenceMS = adjustTime();
log.warn("Adjusted time offset in response to RequestTimeTooSkewed error. "
+ "Local machine and S3 server disagree on the time by approximately "
+ (timeDifferenceMS / 1000) + " seconds. Retrying connection.");
completedWithoutRecoverableError = false;
} else if (responseCode == 500) {
// Retrying after InternalError 500, don't throw exception.
} else if (responseCode == 307) {
// Retrying after Temporary Redirect 307, don't throw exception.
log.debug("Following Temporary Redirect to: " + httpMethod.getURI().toString());
} else {
throw exception;
}
} else {
// Consume response content and release connection.
String responseText = null;
byte[] responseBody = httpMethod.getResponseBody();
if (responseBody != null && responseBody.length > 0) {
responseText = new String(responseBody);
}
log.debug("Releasing error response without XML content");
httpMethod.releaseConnection();
if (responseCode == 500) {
// Retrying after InternalError 500, don't throw exception.
} else {
// Throw exception containing the HTTP error fields.
HttpException httpException = new HttpException(
httpMethod.getStatusCode(), httpMethod.getStatusText());
throw new S3ServiceException("S3 " + httpMethod.getName()
+ " request failed for '" + httpMethod.getPath() + "' - "
+ "ResponseCode=" + httpMethod.getStatusCode()
+ ", ResponseMessage=" + httpMethod.getStatusText()
+ (responseText != null ? "\n" + responseText : ""),
httpException);
}
}
}
} while (!completedWithoutRecoverableError);
// Release immediately any connections without response bodies.
if ((httpMethod.getResponseBodyAsStream() == null
|| httpMethod.getResponseBodyAsStream().available() == 0)
&& httpMethod.getResponseContentLength() == 0)
{
log.debug("Releasing response without content");
byte[] responseBody = httpMethod.getResponseBody();
if (responseBody != null && responseBody.length > 0)
throw new S3ServiceException("Oops, too keen to release connection with a non-empty response body");
httpMethod.releaseConnection();
}
} catch (S3ServiceException e) {
throw e;
} catch (Throwable t) {
log.debug("Releasing method after error: " + t.getMessage());
httpMethod.releaseConnection();
throw new S3ServiceException("S3 " + httpMethod.getName()
+ " connection failed for '" + httpMethod.getPath() + "'", t);
}
}