function bucketPut(authInfo, request, log, callback) {
    log.debug('processing request', { method: 'bucketPut' });

    if (authInfo.isRequesterPublicUser()) {
        log.debug('operation not available for public user');
        monitoring.promMetrics(
            'PUT', request.bucketName, 403, 'createBucket');
        return callback(errors.AccessDenied);
    }
    if (!aclUtils.checkGrantHeaderValidity(request.headers)) {
        log.trace('invalid acl header');
        monitoring.promMetrics(
            'PUT', request.bucketName, 400, 'createBucket');
        return callback(errors.InvalidArgument);
    }
    const { bucketName } = request;


    if (request.bucketName === 'METADATA'
    // Note: for this to work with Vault, would need way to set
    // canonical ID to http://acs.zenko.io/accounts/service/clueso
        && !authInfo.isRequesterThisServiceAccount('clueso')) {
        monitoring.promMetrics(
            'PUT', bucketName, 403, 'createBucket');
        return callback(errorInstances.AccessDenied
            .customizeDescription('The bucket METADATA is used ' +
            'for internal purposes'));
    }

    return waterfall([
        next => _parseXML(request, log, next),
        (locationConstraint, next) => {
            if (!isRequesterNonAccountUser(authInfo)) {
                return next(null, locationConstraint);
            }

            const authParams = auth.server.extractParams(request, log, 's3', request.query);
            const requestConstantParams = authBucketPut(
                authParams, bucketName, locationConstraint, request, authInfo
            );

            return vault.checkPolicies(
                requestConstantParams.map(_buildConstantParams),
                authInfo.getArn(),
                log,
                _handleAuthResults(locationConstraint, log, next),
            );
        },
        (locationConstraint, next) => createBucket(authInfo, bucketName,
          request.headers, locationConstraint, log, (err, previousBucket) => {
              // if bucket already existed, gather any relevant cors
              // headers
              const corsHeaders = collectCorsHeaders(
                  request.headers.origin, request.method, previousBucket);
              if (err) {
                  return next(err, corsHeaders);
              }
              pushMetric('createBucket', log, {
                  authInfo,
                  bucket: bucketName,
              });
              monitoring.promMetrics('PUT', bucketName, '200', 'createBucket');
              return next(null, corsHeaders);
          }),
    ], callback);
}
PUT Service - Create bucket for the user
@param {AuthInfo} authInfo - Instance of AuthInfo class with requester's info
@param {object} request - http request object
@param {object} log - Werelogs logger
@param {function} callback - callback to server
@return {undefined}