Repository: GoogleContainerTools/jib
File: jib-core/src/main/java/com/google/cloud/tools/jib/http/FailoverHttpClient.java (Java)

Code before:
        return Optional.empty(); // No history found. Should go for normal execution path.
    }
  }

  private Response call(String httpMethod, URL url, Request request, HttpTransport httpTransport)
      throws IOException {
    boolean clearAuthorization = !isHttpsProtocol(url) && !sendAuthorizationOverHttp;

    HttpHeaders requestHeaders =
        clearAuthorization
            ? request.getHeaders().clone().setAuthorization((String) null) // deep clone implemented
            : request.getHeaders();

    HttpRequest httpRequest =
        httpTransport
            .createRequestFactory()
            .buildRequest(httpMethod, new GenericUrl(url), request.getHttpContent())
            .setIOExceptionHandler(new HttpBackOffIOExceptionHandler(new ExponentialBackOff()) {
              @Override
              public boolean handleIOException(final HttpRequest request, final boolean supportsRetry) throws IOException {
                final boolean result = super.handleIOException(request, supportsRetry);
                final String reqString = request.getRequestMethod() + " " + request.getUrl();
                if (result) { // google-http-client does not log that properly so let's compensate it
                  logger.accept(LogEvent.warn(reqString + " failed and will be retried"));
                } else {
                  logger.accept(LogEvent.warn(reqString + " failed and will NOT be retried"));
                }
                return result;
              }
            })
            .setUseRawRedirectUrls(true)
            .setHeaders(requestHeaders);
    if (request.getHttpTimeout() != null) {
      httpRequest.setConnectTimeout(request.getHttpTimeout());
      httpRequest.setReadTimeout(request.getHttpTimeout());
    }

    try {
      Response response = new Response(httpRequest.execute());
      synchronized (responsesCreated) {
        responsesCreated.add(response);
      }
      return response;
    } catch (HttpResponseException ex) {
      throw new ResponseException(ex, clearAuthorization);
    }
  }

  private HttpTransport getHttpTransport(boolean secureTransport) {
    HttpTransport transport =
        secureTransport ? secureHttpTransportFactory.get() : insecureHttpTransportFactory.get();

Review comment (bug):
I think the `else` branch can be debug (or removed). 
```suggestion
                  logger.accept(LogEvent.warn(reqString + " failed due to IOException and will be retried"));
                } else {
                  logger.accept(LogEvent.debug(reqString + " failed due to IOException and will NOT be retried"));
```

Code after:
          Response response = call(httpMethod, toHttp(url), request, getHttpTransport(true));
          failoverHistory.put(url.getHost() + ":" + url.getPort(), Failover.HTTP);
          return response;
        }
      }
      throw ex;
    }
  }

  private Optional<Response> followFailoverHistory(String httpMethod, URL url, Request request)
      throws IOException {
    Preconditions.checkArgument(isHttpsProtocol(url));
    switch (failoverHistory.getOrDefault(url.getHost() + ":" + url.getPort(), Failover.NONE)) {
      case HTTP:
        return Optional.of(call(httpMethod, toHttp(url), request, getHttpTransport(true)));
      case INSECURE_HTTPS:
        return Optional.of(call(httpMethod, url, request, getHttpTransport(false)));
      default:
        return Optional.empty(); // No history found. Should go for normal execution path.
    }
  }

  private Response call(String httpMethod, URL url, Request request, HttpTransport httpTransport)
      throws IOException {
    boolean clearAuthorization = !isHttpsProtocol(url) && !sendAuthorizationOverHttp;

    HttpHeaders requestHeaders =
        clearAuthorization
            ? request.getHeaders().clone().setAuthorization((String) null) // deep clone implemented
            : request.getHeaders();

    HttpRequest httpRequest =
        httpTransport
            .createRequestFactory()
            .buildRequest(httpMethod, new GenericUrl(url), request.getHttpContent())
            .setIOExceptionHandler(
                new HttpBackOffIOExceptionHandler(new ExponentialBackOff()) {
                  @Override
                  public boolean handleIOException(HttpRequest request, boolean supportsRetry)
                      throws IOException {
                    boolean result =
                        enableRetries && super.handleIOException(request, supportsRetry);
                    String requestUrl = request.getRequestMethod() + " " + request.getUrl();
                    if (result) { // google-http-client does not log that properly so let's
                      // compensate it
                      logger.accept(LogEvent.warn(requestUrl + " failed and will be retried"));
                    } else {
                      logger.accept(LogEvent.warn(requestUrl + " failed and will NOT be retried"));
                    }
                    return result;
                  }