bucket.js 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. const assert = require('assert');
  2. const { checkBucketName: _checkBucketName } = require('../common/utils/checkBucketName');
  3. const proto = exports;
  4. function isArray(arr) {
  5. if (Array.isArray) return Array.isArray(arr);
  6. return Object.prototype.toString.call(arr) === '[object Array]';
  7. }
  8. function toArray(obj) {
  9. if (!obj) return [];
  10. if (isArray(obj)) return obj;
  11. return [obj];
  12. }
  13. /**
  14. * Bucket opertaions
  15. */
  16. // TODO: OSS server currently do not support CORS requests for bucket operations
  17. // proto.listBuckets = function* listBuckets(query, options) {
  18. // // prefix, marker, max-keys
  19. // var result = yield this.request({
  20. // method: 'GET',
  21. // query: query,
  22. // timeout: options && options.timeout,
  23. // ctx: options && options.ctx,
  24. // });
  25. //
  26. // if (result.status === 200) {
  27. // var data = yield this.parseXML(result.data);
  28. // var buckets = data.Buckets || null;
  29. // if (buckets) {
  30. // if (buckets.Bucket) {
  31. // buckets = buckets.Bucket;
  32. // }
  33. // if (!isArray(buckets)) {
  34. // buckets = [buckets];
  35. // }
  36. // buckets = buckets.map(function (item) {
  37. // return {
  38. // name: item.Name,
  39. // region: item.Location,
  40. // creationDate: item.CreationDate,
  41. // };
  42. // });
  43. // }
  44. // return {
  45. // buckets: buckets,
  46. // owner: {
  47. // id: data.Owner.ID,
  48. // displayName: data.Owner.DisplayName,
  49. // },
  50. // isTruncated: data.IsTruncated === 'true',
  51. // nextMarker: data.NextMarker || null,
  52. // res: result.res
  53. // };
  54. // }
  55. //
  56. // throw yield this.requestError(result);
  57. // };
  58. proto.useBucket = function useBucket(name) {
  59. _checkBucketName(name);
  60. this.options.bucket = name;
  61. return this;
  62. };
  63. proto.setBucket = function useBucket(name) {
  64. _checkBucketName(name);
  65. this.options.bucket = name;
  66. return this;
  67. };
  68. proto.getBucket = function getBucket() {
  69. return this.options.bucket;
  70. };
  71. proto.deleteBucket = async function deleteBucket(name, options) {
  72. const params = this._bucketRequestParams('DELETE', name, '', options);
  73. const result = await this.request(params);
  74. if (result.status === 200 || result.status === 204) {
  75. return {
  76. res: result.res
  77. };
  78. }
  79. throw await this.requestError(result);
  80. };
  81. // acl
  82. proto.putBucketACL = async function putBucketACL(name, acl, options) {
  83. const params = this._bucketRequestParams('PUT', name, 'acl', options);
  84. params.headers = {
  85. 'x-oss-acl': acl
  86. };
  87. params.successStatuses = [200];
  88. const result = await this.request(params);
  89. return {
  90. bucket: (result.headers.location && result.headers.location.substring(1)) || null,
  91. res: result.res
  92. };
  93. };
  94. proto.getBucketACL = async function getBucketACL(name, options) {
  95. const params = this._bucketRequestParams('GET', name, 'acl', options);
  96. params.successStatuses = [200];
  97. params.xmlResponse = true;
  98. const result = await this.request(params);
  99. return {
  100. acl: result.data.AccessControlList.Grant,
  101. owner: {
  102. id: result.data.Owner.ID,
  103. displayName: result.data.Owner.DisplayName
  104. },
  105. res: result.res
  106. };
  107. };
  108. // logging
  109. proto.putBucketLogging = async function putBucketLogging(name, prefix, options) {
  110. const params = this._bucketRequestParams('PUT', name, 'logging', options);
  111. let xml = `${'<?xml version="1.0" encoding="UTF-8"?>\n<BucketLoggingStatus>\n' +
  112. '<LoggingEnabled>\n<TargetBucket>'}${name}</TargetBucket>\n`;
  113. if (prefix) {
  114. xml += `<TargetPrefix>${prefix}</TargetPrefix>\n`;
  115. }
  116. xml += '</LoggingEnabled>\n</BucketLoggingStatus>';
  117. params.content = xml;
  118. params.mime = 'xml';
  119. params.successStatuses = [200];
  120. const result = await this.request(params);
  121. return {
  122. res: result.res
  123. };
  124. };
  125. proto.getBucketLogging = async function getBucketLogging(name, options) {
  126. const params = this._bucketRequestParams('GET', name, 'logging', options);
  127. params.successStatuses = [200];
  128. params.xmlResponse = true;
  129. const result = await this.request(params);
  130. const enable = result.data.LoggingEnabled;
  131. return {
  132. enable: !!enable,
  133. prefix: (enable && enable.TargetPrefix) || null,
  134. res: result.res
  135. };
  136. };
  137. proto.deleteBucketLogging = async function deleteBucketLogging(name, options) {
  138. const params = this._bucketRequestParams('DELETE', name, 'logging', options);
  139. params.successStatuses = [204, 200];
  140. const result = await this.request(params);
  141. return {
  142. res: result.res
  143. };
  144. };
  145. proto.putBucketCORS = async function putBucketCORS(name, rules, options) {
  146. rules = rules || [];
  147. assert(rules.length, 'rules is required');
  148. rules.forEach((rule) => {
  149. assert(rule.allowedOrigin, 'allowedOrigin is required');
  150. assert(rule.allowedMethod, 'allowedMethod is required');
  151. });
  152. const params = this._bucketRequestParams('PUT', name, 'cors', options);
  153. let xml = '<?xml version="1.0" encoding="UTF-8"?>\n<CORSConfiguration>';
  154. const parseOrigin = (val) => {
  155. xml += `<AllowedOrigin>${val}</AllowedOrigin>`;
  156. };
  157. const parseMethod = (val) => {
  158. xml += `<AllowedMethod>${val}</AllowedMethod>`;
  159. };
  160. const parseHeader = (val) => {
  161. xml += `<AllowedHeader>${val}</AllowedHeader>`;
  162. };
  163. const parseExposeHeader = (val) => {
  164. xml += `<ExposeHeader>${val}</ExposeHeader>`;
  165. };
  166. for (let i = 0, l = rules.length; i < l; i++) {
  167. const rule = rules[i];
  168. xml += '<CORSRule>';
  169. toArray(rule.allowedOrigin).forEach(parseOrigin);
  170. toArray(rule.allowedMethod).forEach(parseMethod);
  171. toArray(rule.allowedHeader).forEach(parseHeader);
  172. toArray(rule.exposeHeader).forEach(parseExposeHeader);
  173. if (rule.maxAgeSeconds) {
  174. xml += `<MaxAgeSeconds>${rule.maxAgeSeconds}</MaxAgeSeconds>`;
  175. }
  176. xml += '</CORSRule>';
  177. }
  178. xml += '</CORSConfiguration>';
  179. params.content = xml;
  180. params.mime = 'xml';
  181. params.successStatuses = [200];
  182. const result = await this.request(params);
  183. return {
  184. res: result.res
  185. };
  186. };
  187. proto.getBucketCORS = async function getBucketCORS(name, options) {
  188. const params = this._bucketRequestParams('GET', name, 'cors', options);
  189. params.successStatuses = [200];
  190. params.xmlResponse = true;
  191. const result = await this.request(params);
  192. const rules = [];
  193. if (result.data && result.data.CORSRule) {
  194. let { CORSRule } = result.data;
  195. if (!isArray(CORSRule)) CORSRule = [CORSRule];
  196. CORSRule.forEach((rule) => {
  197. const r = {};
  198. Object.keys(rule).forEach((key) => {
  199. r[key.slice(0, 1).toLowerCase() + key.slice(1, key.length)] = rule[key];
  200. });
  201. rules.push(r);
  202. });
  203. }
  204. return {
  205. rules,
  206. res: result.res
  207. };
  208. };
  209. proto.deleteBucketCORS = async function deleteBucketCORS(name, options) {
  210. const params = this._bucketRequestParams('DELETE', name, 'cors', options);
  211. params.successStatuses = [204];
  212. const result = await this.request(params);
  213. return {
  214. res: result.res
  215. };
  216. };
  217. // referer
  218. proto.putBucketReferer = async function putBucketReferer(name, allowEmpty, referers, options) {
  219. const params = this._bucketRequestParams('PUT', name, 'referer', options);
  220. let xml = '<?xml version="1.0" encoding="UTF-8"?>\n<RefererConfiguration>\n';
  221. xml += ` <AllowEmptyReferer>${allowEmpty ? 'true' : 'false'}</AllowEmptyReferer>\n`;
  222. if (referers && referers.length > 0) {
  223. xml += ' <RefererList>\n';
  224. for (let i = 0; i < referers.length; i++) {
  225. xml += ` <Referer>${referers[i]}</Referer>\n`;
  226. }
  227. xml += ' </RefererList>\n';
  228. } else {
  229. xml += ' <RefererList />\n';
  230. }
  231. xml += '</RefererConfiguration>';
  232. params.content = xml;
  233. params.mime = 'xml';
  234. params.successStatuses = [200];
  235. const result = await this.request(params);
  236. return {
  237. res: result.res
  238. };
  239. };
  240. proto.getBucketReferer = async function getBucketReferer(name, options) {
  241. const params = this._bucketRequestParams('GET', name, 'referer', options);
  242. params.successStatuses = [200];
  243. params.xmlResponse = true;
  244. const result = await this.request(params);
  245. let referers = result.data.RefererList.Referer || null;
  246. if (referers) {
  247. if (!isArray(referers)) {
  248. referers = [referers];
  249. }
  250. }
  251. return {
  252. allowEmpty: result.data.AllowEmptyReferer === 'true',
  253. referers,
  254. res: result.res
  255. };
  256. };
  257. proto.deleteBucketReferer = async function deleteBucketReferer(name, options) {
  258. return await this.putBucketReferer(name, true, null, options);
  259. };
  260. // private apis
  261. proto._bucketRequestParams = function _bucketRequestParams(method, bucket, subres, options) {
  262. return {
  263. method,
  264. bucket,
  265. subres,
  266. timeout: options && options.timeout,
  267. ctx: options && options.ctx
  268. };
  269. };