Repository: corona-warn-app/cwa-server
File: services/download/src/main/java/app/coronawarn/server/services/download/FederationGatewayDownloadService.java (Java)

Code before:
      ResponseEntity<DiagnosisKeyBatch> response = federationGatewayClient
          .getDiagnosisKeys(batchTag, dateString);
      return parseResponseEntity(response);
    } catch (FeignException.Forbidden feignException) {
      throw new FatalFederationGatewayException(
          "Downloading batch " + batchTag + " for date " + date.format(ISO_LOCAL_DATE)
              + " failed due to invalid client certificate.");
    } catch (FeignException exception) {
      logger.error("Downloading batch for date {} and batchTag {} failed. Reason: {}", batchTag, dateString,
          exception.getMessage());
      throw new BatchDownloadException("Downloading batch " + batchTag + " for date " + date + " failed.",
          exception);
    }
  }

  /**
   * Audit the batch from the EFGS for the given date.
   *
   * @param batchTag The batchTag of the batch that should be audited.
   * @param date     The date for which the batch should be audited.
   */
  public void auditBatch(String batchTag, LocalDate date) {
    try {
      ResponseEntity<String> auditInformation = federationGatewayClient
          .getAuditInformation(date.format(ISO_LOCAL_DATE), batchTag);
      logger.info("Retrieved response from EFGS:{}", auditInformation);
    } catch (FeignException.BadRequest | FeignException.Forbidden | FeignException.NotAcceptable
        | FeignException.Gone | FeignException.NotFound clientError) {
      logger.error("Auditing batch " + batchTag + " for date " + date.format(ISO_LOCAL_DATE)
          + " failed due to: " + clientError.getMessage());
      throw new BatchAuditException("Downloading batch " + batchTag + " for date " + date + " failed due to: "
          + clientError.getMessage());
    } catch (FeignException e) {
      logger.error("Auditing batch " + batchTag + " for date " + date.format(ISO_LOCAL_DATE)
          + " failed due to uncommon reason: " + e.getMessage());
      throw new BatchAuditException("Downloading batch " + batchTag + " for date " + date
          + " failed due to uncommon reason: " + e.getMessage());
    }
  }

  private BatchDownloadResponse parseResponseEntity(ResponseEntity<DiagnosisKeyBatch> response) {
    String batchTag = getHeader(response, HEADER_BATCH_TAG)
        .orElseThrow(() -> new BatchDownloadException("Missing " + HEADER_BATCH_TAG + " header."));
    Optional<String> nextBatchTag = getHeader(response, HEADER_NEXT_BATCH_TAG);
    return new BatchDownloadResponse(batchTag, Optional.ofNullable(response.getBody()), nextBatchTag);
  }

  private Optional<String> getHeader(ResponseEntity<DiagnosisKeyBatch> response, String header) {
    String headerString = response.getHeaders().getFirst(header);
    return (!EMPTY_HEADER.equals(headerString))
        ? Optional.ofNullable(headerString)

Review comment (bug):
Do we need to log the whole response from EFGS on info level? It might be worth to log it only if the spring profile`debug` is enabled.

Code after:
      ResponseEntity<DiagnosisKeyBatch> response = federationGatewayClient
          .getDiagnosisKeys(batchTag, dateString);
      return parseResponseEntity(response);
    } catch (FeignException.Forbidden feignException) {
      throw new FatalFederationGatewayException(
          "Downloading batch " + batchTag + " for date " + getDateAsString(date)
              + " failed due to invalid client certificate.");
    } catch (FeignException exception) {
      logger.error("Downloading batch for date {} and batchTag {} failed. Reason: {}", batchTag, dateString,
          exception.getMessage());
      throw new BatchDownloadException("Downloading batch " + batchTag + " for date " + date + " failed.",
          exception);
    }
  }

  /**
   * Audit the batch from the EFGS for the given date.
   *
   * @param batchTag The batchTag of the batch that should be audited.
   * @param date     The date for which the batch should be audited.
   */
  public void auditBatch(String batchTag, LocalDate date) {
    try {
      logger.info("Auditing batch for date {} and batchTag {}.", getDateAsString(date), batchTag);
      ResponseEntity<String> auditInformation = federationGatewayClient
          .getAuditInformation(getDateAsString(date), batchTag);
      logger.debug("Retrieved audit response from EFGS: {}", auditInformation);
    } catch (FeignException.BadRequest | FeignException.Forbidden | FeignException.NotAcceptable
        | FeignException.Gone | FeignException.NotFound clientError) {
      logger.error("Auditing batch {} for date {} failed due to: {}", batchTag, getDateAsString(date),
          clientError.getMessage());
      throw new BatchAuditException(
          String.format("Auditing batch %s for date %s failed due to: %s", batchTag, date, clientError.getMessage()),
          clientError);
    } catch (FeignException e) {
      logger.error("Auditing batch {} for date {} failed due to uncommon reason: {}", batchTag,
          getDateAsString(date), e.getMessage());
      throw new BatchAuditException(String
          .format("Auditing batch %s  for date %s failed due to uncommon reason: %s", batchTag, date, e.getMessage()),
          e);
    }
  }

  private String getDateAsString(LocalDate date) {
    return date.format(ISO_LOCAL_DATE);
  }

  private BatchDownloadResponse parseResponseEntity(ResponseEntity<DiagnosisKeyBatch> response) {
    String batchTag = getHeader(response, HEADER_BATCH_TAG)
        .orElseThrow(() -> new BatchDownloadException("Missing " + HEADER_BATCH_TAG + " header."));
    Optional<String> nextBatchTag = getHeader(response, HEADER_NEXT_BATCH_TAG);