private RedirectFollowingResult followRedirects()

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);
    }
  }