in s3-artifact-storage-agent/src/main/java/jetbrains/buildServer/artifacts/s3/download/S3ArtifactTransport.java [106:155]
private RedirectFollowingResult followRedirects(@NotNull String srcUrl, @NotNull Path targetFile, @NotNull FileProgress downloadProgress, int redirectLevel) throws IOException {
GetMethod request = new GetMethod(srcUrl);
UUID requestId = UUID.randomUUID();
try {
checkIfInterrupted();
myPendingRequestsById.compute(requestId, (id, oldRequest) -> {
if (oldRequest != null) {
// we have a UUID collision (astronomically low likelihood)
LOGGER.warn("Request UUID collision, releasing connection of the previous request");
releaseConnectionIfNotNull(oldRequest);
}
return request;
});
checkIfInterrupted();
int statusCode = myhttpClient.execute(request);
if (isRedirectStatus(statusCode)) {
checkIfInterrupted();
if (redirectLevel >= myMaxRedirects) throw new RedirectException(String.format("Maximum number of redirects (%s) exceeded", myMaxRedirects));
Header location = request.getResponseHeader("Location");
if (location == null) throw new IOException(String.format("Status code %s requires redirect, but no \"Location\" header provided", statusCode));
releaseConnectionIfNotNull(request);
return followRedirects(getNormalizedLocation(request, location), targetFile, downloadProgress, redirectLevel + 1);
}
checkResponseStatus(statusCode, HttpStatus.SC_OK);
LOGGER.debug(String.format("Found direct URL for downloading file %s: %s", targetFile, srcUrl));
Long contentLength = getContentLength(request);
String fileDigest = myDependencyHttpHelper.fetchDigest(request);
if (isParallelisationPossible(srcUrl, targetFile, contentLength, canAcceptByteRanges(request))) {
// abort request not to wait until full response body arrives
// this closes the associated connection, but this is fine because it happens only once per large file that will be downloaded in parallel
request.abort();
return new RedirectFollowingResult(true, srcUrl, contentLength, fileDigest);
}
// perform sequential download right away
LOGGER.debug(String.format("Start downloading file %s from %s sequentially", targetFile, srcUrl));
downloadSequentially(request, targetFile, contentLength, downloadProgress);
return new RedirectFollowingResult(false, srcUrl, contentLength, fileDigest);
} finally {
releaseConnectionIfNotNull(request);
myPendingRequestsById.remove(requestId);
}
}