const assert = require('assert');
const { checkBucketName: _checkBucketName } = require('../common/utils/checkBucketName');
const proto = exports;
function isArray(arr) {
if (Array.isArray) return Array.isArray(arr);
return Object.prototype.toString.call(arr) === '[object Array]';
}
function toArray(obj) {
if (!obj) return [];
if (isArray(obj)) return obj;
return [obj];
}
/**
* Bucket opertaions
*/
// TODO: OSS server currently do not support CORS requests for bucket operations
// proto.listBuckets = function* listBuckets(query, options) {
// // prefix, marker, max-keys
// var result = yield this.request({
// method: 'GET',
// query: query,
// timeout: options && options.timeout,
// ctx: options && options.ctx,
// });
//
// if (result.status === 200) {
// var data = yield this.parseXML(result.data);
// var buckets = data.Buckets || null;
// if (buckets) {
// if (buckets.Bucket) {
// buckets = buckets.Bucket;
// }
// if (!isArray(buckets)) {
// buckets = [buckets];
// }
// buckets = buckets.map(function (item) {
// return {
// name: item.Name,
// region: item.Location,
// creationDate: item.CreationDate,
// };
// });
// }
// return {
// buckets: buckets,
// owner: {
// id: data.Owner.ID,
// displayName: data.Owner.DisplayName,
// },
// isTruncated: data.IsTruncated === 'true',
// nextMarker: data.NextMarker || null,
// res: result.res
// };
// }
//
// throw yield this.requestError(result);
// };
proto.useBucket = function useBucket(name) {
_checkBucketName(name);
this.options.bucket = name;
return this;
};
proto.setBucket = function useBucket(name) {
_checkBucketName(name);
this.options.bucket = name;
return this;
};
proto.getBucket = function getBucket() {
return this.options.bucket;
};
proto.deleteBucket = async function deleteBucket(name, options) {
const params = this._bucketRequestParams('DELETE', name, '', options);
const result = await this.request(params);
if (result.status === 200 || result.status === 204) {
return {
res: result.res
};
}
throw await this.requestError(result);
};
// acl
proto.putBucketACL = async function putBucketACL(name, acl, options) {
const params = this._bucketRequestParams('PUT', name, 'acl', options);
params.headers = {
'x-oss-acl': acl
};
params.successStatuses = [200];
const result = await this.request(params);
return {
bucket: (result.headers.location && result.headers.location.substring(1)) || null,
res: result.res
};
};
proto.getBucketACL = async function getBucketACL(name, options) {
const params = this._bucketRequestParams('GET', name, 'acl', options);
params.successStatuses = [200];
params.xmlResponse = true;
const result = await this.request(params);
return {
acl: result.data.AccessControlList.Grant,
owner: {
id: result.data.Owner.ID,
displayName: result.data.Owner.DisplayName
},
res: result.res
};
};
// logging
proto.putBucketLogging = async function putBucketLogging(name, prefix, options) {
const params = this._bucketRequestParams('PUT', name, 'logging', options);
let xml = `${'\n\n\n'}${name}\n`;
if (prefix) {
xml += `${prefix}\n`;
}
xml += '\n';
params.content = xml;
params.mime = 'xml';
params.successStatuses = [200];
const result = await this.request(params);
return {
res: result.res
};
};
proto.getBucketLogging = async function getBucketLogging(name, options) {
const params = this._bucketRequestParams('GET', name, 'logging', options);
params.successStatuses = [200];
params.xmlResponse = true;
const result = await this.request(params);
const enable = result.data.LoggingEnabled;
return {
enable: !!enable,
prefix: (enable && enable.TargetPrefix) || null,
res: result.res
};
};
proto.deleteBucketLogging = async function deleteBucketLogging(name, options) {
const params = this._bucketRequestParams('DELETE', name, 'logging', options);
params.successStatuses = [204, 200];
const result = await this.request(params);
return {
res: result.res
};
};
proto.putBucketCORS = async function putBucketCORS(name, rules, options) {
rules = rules || [];
assert(rules.length, 'rules is required');
rules.forEach(rule => {
assert(rule.allowedOrigin, 'allowedOrigin is required');
assert(rule.allowedMethod, 'allowedMethod is required');
});
const params = this._bucketRequestParams('PUT', name, 'cors', options);
let xml = '\n';
const parseOrigin = val => {
xml += `${val}`;
};
const parseMethod = val => {
xml += `${val}`;
};
const parseHeader = val => {
xml += `${val}`;
};
const parseExposeHeader = val => {
xml += `${val}`;
};
for (let i = 0, l = rules.length; i < l; i++) {
const rule = rules[i];
xml += '';
toArray(rule.allowedOrigin).forEach(parseOrigin);
toArray(rule.allowedMethod).forEach(parseMethod);
toArray(rule.allowedHeader).forEach(parseHeader);
toArray(rule.exposeHeader).forEach(parseExposeHeader);
if (rule.maxAgeSeconds) {
xml += `${rule.maxAgeSeconds}`;
}
xml += '';
}
xml += '';
params.content = xml;
params.mime = 'xml';
params.successStatuses = [200];
const result = await this.request(params);
return {
res: result.res
};
};
proto.getBucketCORS = async function getBucketCORS(name, options) {
const params = this._bucketRequestParams('GET', name, 'cors', options);
params.successStatuses = [200];
params.xmlResponse = true;
const result = await this.request(params);
const rules = [];
if (result.data && result.data.CORSRule) {
let { CORSRule } = result.data;
if (!isArray(CORSRule)) CORSRule = [CORSRule];
CORSRule.forEach(rule => {
const r = {};
Object.keys(rule).forEach(key => {
r[key.slice(0, 1).toLowerCase() + key.slice(1, key.length)] = rule[key];
});
rules.push(r);
});
}
return {
rules,
res: result.res
};
};
proto.deleteBucketCORS = async function deleteBucketCORS(name, options) {
const params = this._bucketRequestParams('DELETE', name, 'cors', options);
params.successStatuses = [204];
const result = await this.request(params);
return {
res: result.res
};
};
// referer
proto.putBucketReferer = async function putBucketReferer(name, allowEmpty, referers, options) {
const params = this._bucketRequestParams('PUT', name, 'referer', options);
let xml = '\n\n';
xml += ` ${allowEmpty ? 'true' : 'false'}\n`;
if (referers && referers.length > 0) {
xml += ' \n';
for (let i = 0; i < referers.length; i++) {
xml += ` ${referers[i]}\n`;
}
xml += ' \n';
} else {
xml += ' \n';
}
xml += '';
params.content = xml;
params.mime = 'xml';
params.successStatuses = [200];
const result = await this.request(params);
return {
res: result.res
};
};
proto.getBucketReferer = async function getBucketReferer(name, options) {
const params = this._bucketRequestParams('GET', name, 'referer', options);
params.successStatuses = [200];
params.xmlResponse = true;
const result = await this.request(params);
let referers = result.data.RefererList.Referer || null;
if (referers) {
if (!isArray(referers)) {
referers = [referers];
}
}
return {
allowEmpty: result.data.AllowEmptyReferer === 'true',
referers,
res: result.res
};
};
proto.deleteBucketReferer = async function deleteBucketReferer(name, options) {
return await this.putBucketReferer(name, true, null, options);
};
// private apis
proto._bucketRequestParams = function _bucketRequestParams(method, bucket, subres, options) {
return {
method,
bucket,
subres,
additionalHeaders: options && options.additionalHeaders,
timeout: options && options.timeout,
ctx: options && options.ctx
};
};