bucket.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. 'use strict';
  2. const assert = require('assert');
  3. var proto = exports;
  4. /**
  5. * Bucket opertaions
  6. */
  7. proto.listBuckets = function* listBuckets(query, options) {
  8. // prefix, marker, max-keys
  9. var result = yield this.request({
  10. method: 'GET',
  11. query: query,
  12. timeout: options && options.timeout,
  13. ctx: options && options.ctx,
  14. });
  15. if (result.status === 200) {
  16. var data = yield this.parseXML(result.data);
  17. var buckets = data.Buckets || null;
  18. if (buckets) {
  19. if (buckets.Bucket) {
  20. buckets = buckets.Bucket;
  21. }
  22. if (!isArray(buckets)) {
  23. buckets = [buckets];
  24. }
  25. buckets = buckets.map(function (item) {
  26. return {
  27. name: item.Name,
  28. region: item.Location,
  29. creationDate: item.CreationDate,
  30. };
  31. });
  32. }
  33. return {
  34. buckets: buckets,
  35. owner: {
  36. id: data.Owner.ID,
  37. displayName: data.Owner.DisplayName,
  38. },
  39. isTruncated: data.IsTruncated === 'true',
  40. nextMarker: data.NextMarker || null,
  41. res: result.res
  42. };
  43. }
  44. throw yield this.requestError(result);
  45. };
  46. proto.useBucket = function useBucket(name, region) {
  47. this.options.bucket = name;
  48. return this;
  49. };
  50. proto.putBucket = function* putBucket(name, region, options) {
  51. var params = this._bucketRequestParams('PUT', name, '', options);
  52. if (region) {
  53. params.mime = 'xml';
  54. params.content = '<?xml version="1.0" encoding="UTF-8"?>\n' +
  55. '<CreateBucketConfiguration><LocationConstraint>' + region +
  56. '</LocationConstraint></CreateBucketConfiguration>';
  57. }
  58. params.successStatuses = [200];
  59. var result = yield this.request(params);
  60. return {
  61. bucket: result.headers.location && result.headers.location.substring(1) || null,
  62. res: result.res
  63. };
  64. };
  65. proto.deleteBucket = function* deleteBucket(name, region, options) {
  66. var params = this._bucketRequestParams('DELETE', name, '', options);
  67. var result = yield this.request(params);
  68. if (result.status === 200 || result.status === 204) {
  69. return {
  70. res: result.res
  71. };
  72. }
  73. throw yield this.requestError(result);
  74. };
  75. // acl
  76. proto.putBucketACL = function* putBucketACL(name, region, acl, options) {
  77. var params = this._bucketRequestParams('PUT', name, 'acl', options);
  78. params.headers = {
  79. 'x-oss-acl': acl
  80. };
  81. params.successStatuses = [200];
  82. var result = yield this.request(params);
  83. return {
  84. bucket: result.headers.location && result.headers.location.substring(1) || null,
  85. res: result.res
  86. };
  87. };
  88. proto.getBucketACL = function* getBucketACL(name, region, options) {
  89. var params = this._bucketRequestParams('GET', name, 'acl', options);
  90. params.successStatuses = [200];
  91. params.xmlResponse = true;
  92. var result = yield this.request(params);
  93. return {
  94. acl: result.data.AccessControlList.Grant,
  95. owner: {
  96. id: result.data.Owner.ID,
  97. displayName: result.data.Owner.DisplayName,
  98. },
  99. res: result.res
  100. };
  101. };
  102. // logging
  103. proto.putBucketLogging = function* putBucketLogging(name, region, prefix, options) {
  104. var params = this._bucketRequestParams('PUT', name, 'logging', options);
  105. var xml = '<?xml version="1.0" encoding="UTF-8"?>\n<BucketLoggingStatus>\n' +
  106. '<LoggingEnabled>\n<TargetBucket>' + name + '</TargetBucket>\n';
  107. if (prefix) {
  108. xml += '<TargetPrefix>' + prefix + '</TargetPrefix>\n';
  109. }
  110. xml += '</LoggingEnabled>\n</BucketLoggingStatus>';
  111. params.content = xml;
  112. params.mime = 'xml';
  113. params.successStatuses = [200];
  114. var result = yield this.request(params);
  115. return {
  116. res: result.res
  117. };
  118. };
  119. proto.getBucketLogging = function* getBucketLogging(name, region, options) {
  120. var params = this._bucketRequestParams('GET', name, 'logging', options);
  121. params.successStatuses = [200];
  122. params.xmlResponse = true;
  123. var result = yield this.request(params);
  124. var enable = result.data.LoggingEnabled;
  125. return {
  126. enable: !!enable,
  127. prefix: enable && enable.TargetPrefix || null,
  128. res: result.res,
  129. };
  130. };
  131. proto.deleteBucketLogging = function* deleteBucketLogging(name, region, options) {
  132. var params = this._bucketRequestParams('DELETE', name, 'logging', options);
  133. params.successStatuses = [204, 200];
  134. var result = yield this.request(params);
  135. return {
  136. res: result.res,
  137. };
  138. };
  139. // website
  140. proto.putBucketWebsite = function* putBucketWebsite(name, region, config, options) {
  141. // config: index, [error]
  142. var params = this._bucketRequestParams('PUT', name, 'website', options);
  143. config = config || {};
  144. config.index = config.index || 'index.html';
  145. var xml = '<?xml version="1.0" encoding="UTF-8"?>\n<WebsiteConfiguration>\n' +
  146. ' <IndexDocument><Suffix>' + config.index + '</Suffix></IndexDocument>\n';
  147. if (config.error) {
  148. xml += '<ErrorDocument><Key>' + config.error + '</Key></ErrorDocument>\n';
  149. }
  150. xml += '</WebsiteConfiguration>';
  151. params.content = xml;
  152. params.mime = 'xml';
  153. params.successStatuses = [200];
  154. var result = yield* this.request(params);
  155. return {
  156. res: result.res
  157. };
  158. };
  159. proto.getBucketWebsite = function* getBucketWebsite(name, region, options) {
  160. var params = this._bucketRequestParams('GET', name, 'website', options);
  161. params.successStatuses = [200];
  162. params.xmlResponse = true;
  163. var result = yield this.request(params);
  164. return {
  165. index: result.data.IndexDocument.Suffix,
  166. error: result.data.ErrorDocument && result.data.ErrorDocument.Key || null,
  167. res: result.res
  168. };
  169. };
  170. proto.deleteBucketWebsite = function* deleteBucketWebsite(name, region, options) {
  171. var params = this._bucketRequestParams('DELETE', name, 'website', options);
  172. params.successStatuses = [204];
  173. var result = yield this.request(params);
  174. return {
  175. res: result.res
  176. };
  177. };
  178. // lifecycle
  179. proto.putBucketLifecycle = function* putBucketLifecycle(name, region, rules, options) {
  180. // rules: [rule, ...]
  181. // rule: [id], prefix, status, expiration, [days or date]
  182. // status: 'Enabled' or 'Disabled'
  183. var params = this._bucketRequestParams('PUT', name, 'lifecycle', options);
  184. var xml = '<?xml version="1.0" encoding="UTF-8"?>\n<LifecycleConfiguration>\n';
  185. for (var i = 0; i < rules.length; i++) {
  186. var rule = rules[i];
  187. var expiration = rule.days ?
  188. '<Days>' + rule.days + '</Days>'
  189. :
  190. '<Date>' + rule.date + '</Date>';
  191. var id = rule.id ? '<ID>' + rule.id + '</ID>\n' : '';
  192. xml += ' <Rule>\n' + id +
  193. ' <Prefix>' + rule.prefix + '</Prefix>\n' +
  194. ' <Status>' + rule.status + '</Status>\n' +
  195. ' <Expiration>' + expiration + '</Expiration>\n' +
  196. ' </Rule>\n';
  197. }
  198. xml += '</LifecycleConfiguration>';
  199. params.content = xml;
  200. params.mime = 'xml';
  201. params.successStatuses = [200];
  202. var result = yield this.request(params);
  203. return {
  204. res: result.res
  205. };
  206. };
  207. proto.getBucketLifecycle = function* getBucketLifecycle(name, region, options) {
  208. var params = this._bucketRequestParams('GET', name, 'lifecycle', options);
  209. params.successStatuses = [200];
  210. params.xmlResponse = true;
  211. var result = yield this.request(params);
  212. var rules = result.data.Rule || null;
  213. if (rules) {
  214. if (!isArray(rules)) {
  215. rules = [rules];
  216. }
  217. rules = rules.map(function (rule) {
  218. var item = {
  219. id: rule.ID,
  220. prefix: rule.Prefix,
  221. status: rule.Status,
  222. };
  223. if (rule.Expiration.Days) {
  224. item.days = rule.Expiration.Days;
  225. } else {
  226. item.date = rule.Expiration.Date;
  227. }
  228. return item;
  229. });
  230. }
  231. return {
  232. rules: rules,
  233. res: result.res
  234. };
  235. };
  236. proto.deleteBucketLifecycle = function* deleteBucketLifecycle(name, region, options) {
  237. var params = this._bucketRequestParams('DELETE', name, 'lifecycle', options);
  238. params.successStatuses = [204];
  239. var result = yield this.request(params);
  240. return {
  241. res: result.res
  242. };
  243. };
  244. proto.putBucketCORS = function* (name, region, rules, options) {
  245. rules = rules || [];
  246. assert(rules.length, 'rules is required');
  247. rules.forEach(rule => {
  248. assert(rule.allowedOrigin, 'allowedOrigin is required');
  249. assert(rule.allowedMethod, 'allowedMethod is required');
  250. });
  251. var params = this._bucketRequestParams('PUT', name, 'cors', options);
  252. var xml = '<?xml version="1.0" encoding="UTF-8"?>\n<CORSConfiguration>';
  253. for (var i = 0, l = rules.length; i < l; i++) {
  254. var rule = rules[i];
  255. xml += '<CORSRule>';
  256. toArray(rule.allowedOrigin).forEach(function(val) {
  257. xml += '<AllowedOrigin>' + val + '</AllowedOrigin>';
  258. });
  259. toArray(rule.allowedMethod).forEach(function(val) {
  260. xml += '<AllowedMethod>' + val + '</AllowedMethod>';
  261. });
  262. toArray(rule.allowedHeader).forEach(function(val) {
  263. xml += '<AllowedHeader>' + val + '</AllowedHeader>';
  264. });
  265. toArray(rule.exposeHeader).forEach(function(val) {
  266. xml += '<ExposeHeader>' + val + '</ExposeHeader>';
  267. });
  268. if (rule.maxAgeSeconds) {
  269. xml += '<MaxAgeSeconds>' + rule.maxAgeSeconds + '</MaxAgeSeconds>';
  270. }
  271. xml += '</CORSRule>';
  272. }
  273. xml += '</CORSConfiguration>';
  274. params.content = xml;
  275. params.mime = 'xml';
  276. params.successStatuses = [200];
  277. var result = yield this.request(params);
  278. return {
  279. res: result.res
  280. };
  281. };
  282. proto.getBucketCORS = function* (name, region, options) {
  283. var params = this._bucketRequestParams('GET', name, 'cors', options);
  284. params.successStatuses = [200];
  285. params.xmlResponse = true;
  286. var result = yield this.request(params);
  287. var rules = [];
  288. if (result.data && result.data.CORSRule) {
  289. var CORSRule = result.data.CORSRule;
  290. if (!isArray(CORSRule)) CORSRule = [ CORSRule ];
  291. CORSRule.forEach(function(rule) {
  292. var r = {};
  293. for (const name in rule) {
  294. r[name.slice(0, 1).toLowerCase() + name.slice(1, name.length)] = rule[name];
  295. }
  296. rules.push(r);
  297. });
  298. }
  299. return {
  300. rules: rules,
  301. res: result.res
  302. };
  303. };
  304. proto.deleteBucketCORS = function* (name, region, options) {
  305. var params = this._bucketRequestParams('DELETE', name, 'cors', options);
  306. params.successStatuses = [204];
  307. var result = yield this.request(params);
  308. return {
  309. res: result.res
  310. };
  311. };
  312. // referer
  313. proto.putBucketReferer = function* putBucketReferer(name, region, allowEmpty, referers, options) {
  314. var params = this._bucketRequestParams('PUT', name, 'referer', options);
  315. var xml = '<?xml version="1.0" encoding="UTF-8"?>\n<RefererConfiguration>\n';
  316. xml += ' <AllowEmptyReferer>' + (allowEmpty ? 'true' : 'false') + '</AllowEmptyReferer>\n';
  317. if (referers && referers.length > 0) {
  318. xml += ' <RefererList>\n';
  319. for (var i = 0; i < referers.length; i++) {
  320. xml += ' <Referer>' + referers[i] + '</Referer>\n';
  321. }
  322. xml += ' </RefererList>\n';
  323. } else {
  324. xml += ' <RefererList />\n';
  325. }
  326. xml += '</RefererConfiguration>';
  327. params.content = xml;
  328. params.mime = 'xml';
  329. params.successStatuses = [200];
  330. var result = yield this.request(params);
  331. return {
  332. res: result.res,
  333. };
  334. };
  335. proto.getBucketReferer = function* getBucketReferer(name, region, options) {
  336. var params = this._bucketRequestParams('GET', name, 'referer', options);
  337. params.successStatuses = [200];
  338. params.xmlResponse = true;
  339. var result = yield this.request(params);
  340. var referers = result.data.RefererList.Referer || null;
  341. if (referers) {
  342. if (!isArray(referers)) {
  343. referers = [referers];
  344. }
  345. }
  346. return {
  347. allowEmpty: result.data.AllowEmptyReferer === 'true',
  348. referers: referers,
  349. res: result.res
  350. };
  351. };
  352. proto.deleteBucketReferer = function* deleteBucketReferer(name, region, options) {
  353. return yield this.putBucketReferer(name, region, true, null, options);
  354. };
  355. // private apis
  356. proto._bucketRequestParams = function _bucketRequestParams(method, bucket, subres, options) {
  357. return {
  358. method: method,
  359. bucket: bucket,
  360. subres: subres,
  361. timeout: options && options.timeout,
  362. ctx: options && options.ctx,
  363. };
  364. };
  365. function isArray(arr) {
  366. if (Array.isArray) return Array.isArray(arr);
  367. return Object.prototype.toString.call(arr) === '[object Array]';
  368. }
  369. function toArray(obj) {
  370. if (!obj) return [];
  371. if (isArray(obj)) return obj;
  372. return [ obj ];
  373. }