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