private Callback<Void> securityPostProcessRequestCallback(BlobInfo blobInfo) {
      return buildCallback(frontendMetrics.postSecurityPostProcessRequestMetrics, securityCheckResult -> {
        if (RestUtils.getRequestPath(restRequest).matchesOperation(Operations.STITCH)) {
          RetainingAsyncWritableChannel channel =
              new RetainingAsyncWritableChannel(frontendConfig.maxJsonRequestSizeBytes);
          restRequest.readInto(channel, fetchStitchRequestBodyCallback(channel, blobInfo));
        } 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/PostBlobHandler.java