@Override
    public void onCompletion(Void result, Exception exception) {
      long processingStartTimeMs = SystemTime.getInstance().milliseconds();
      metrics.getSignedUrlSecurityRequestTimeInMs.update(processingStartTimeMs - operationStartTimeMs);
      try {
        if (exception == null) {
          switch (restMethodInUrl) {
            case GET:
              String blobIdStr = RestUtils.getHeader(restRequest.getArgs(), RestUtils.Headers.BLOB_ID, true);
              IdConverterCallback idConverterCallback =
                  new IdConverterCallback(restRequest, restResponseChannel, callback);
              idConverter.convert(restRequest, blobIdStr, idConverterCallback);
              break;
            case POST:
              accountAndContainerInjector.injectAccountAndContainerForPostRequest(restRequest,
                  metrics.getSignedUrlMetricsGroup);
              securityService.postProcessRequest(restRequest,
                  new SecurityPostProcessRequestCallback(restRequest, restResponseChannel, callback));
              break;
            default:
              exception = new RestServiceException("Getting signed URLs for " + restMethodInUrl + " is not supported",
                  RestServiceErrorCode.BadRequest);
          }
        }
      } catch (Exception e) {
        exception = e;
      } finally {
        metrics.getSignedUrlSecurityRequestCallbackProcessingTimeInMs.update(
            SystemTime.getInstance().milliseconds() - processingStartTimeMs);
        if (exception != null) {
          callback.onCompletion(null, exception);
        }
      }
    }
Callback for {@link SecurityService#processRequest(RestRequest, Callback)} that subsequently calls
{@link SecurityService#postProcessRequest(RestRequest, Callback)}. If post processing succeeds, a signed URL will
be generated.
ambry-frontend/src/main/java/com/github/ambry/frontend/GetSignedUrlHandler.java