private Callback<Void> securityPostProcessRequestCallback(BlobInfo blobInfo) {
      return buildCallback(frontendMetrics.putSecurityPostProcessRequestMetrics, securityCheckResult -> {
        if (frontendConfig.oneHundredContinueEnable && CONTINUE.equals(restRequest.getArgs().get(EXPECT))) {
          restResponseChannel.setStatus(ResponseStatus.Continue);
          //We need to set the content length in order to be a full http response in NettyResponseChannel::maybeWriteResponseMetadata.
          restResponseChannel.setHeader(RestUtils.Headers.CONTENT_LENGTH, 0);
          finalCallback.onCompletion(null, null);
        } else {
          PutBlobOptions options = getPutBlobOptionsFromRequest();
          router.putBlob(null, blobInfo.getBlobProperties(), blobInfo.getUserMetadata(), restRequest, options,
              routerPutBlobCallback(blobInfo), QuotaUtils.buildQuotaChargeCallback(restRequest, quotaManager, true));
        }
      }, uri, logger, finalCallback);
    }
After {@link SecurityService#postProcessRequest} finishes, call {@link Router#putBlob} to persist the blob in the
storage layer.
@param blobInfo the {@link BlobInfo} to make the router call with.
@return a {@link Callback} to be used with {@link SecurityService#postProcessRequest}.
ambry-frontend/src/main/java/com/github/ambry/frontend/s3/S3MultipartUploadPartHandler.java