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, timeout: options && options.timeout, ctx: options && options.ctx }; };