Skip to content

Commit 6a76ebf

Browse files
author
carsonxu
committed
优化错误提示/测试用例
1 parent 7ceb417 commit 6a76ebf

File tree

4 files changed

+83
-74
lines changed

4 files changed

+83
-74
lines changed

index.d.ts

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,9 @@ declare namespace COS {
172172
/** 获取签名的回调方法,如果没有 SecretId、SecretKey 时,必选 */
173173
getAuthorization?: (
174174
options: GetAuthorizationOptions,
175-
/** 获取完签名或临时密钥后,回传给 SDK 的方法 */
175+
/** callback 获取完签名或临时密钥后,回传给 SDK 的方法 */
176176
callback: (
177-
/** 回传给 SDK 的签名或获取临时密钥 */
177+
/** params 回传给 SDK 的签名或获取临时密钥 */
178178
params: GetAuthorizationCallbackParams
179179
) => void
180180
) => void,
@@ -217,6 +217,7 @@ declare namespace COS {
217217
/** 校正时间的偏移值,单位 ms(毫秒),计算签名时会用设备当前时间戳加上该偏移值,在设备时间有误时可用于校正签名用的时间参数。 */
218218
SystemClockOffset: number,
219219
}
220+
/** 请求凭证,包含临时密钥信息 */
220221
interface Credentials {
221222
/** 临时密钥 tmpSecretId */
222223
TmpSecretId: string,
@@ -238,26 +239,27 @@ declare namespace COS {
238239
type Authorization = string;
239240
/** SDK 用于请求的凭证,可以是签名,也可以是临时密钥信息 */
240241
type GetAuthorizationCallbackParams = Authorization | Credentials;
241-
/** 错误格式,其中服务端返回错误码可查看 @see https://cloud.tencent.com/document/product/436/7730 */
242-
type CosError = null | {
242+
/** 一般接口的返回结果 */
243+
interface GeneralResult {
243244
/** 请求返回的 HTTP 状态码 */
244245
statusCode?: number,
245246
/** 请求返回的 header 字段 */
246247
headers?: Headers,
248+
/** 请求的唯一标识 */
249+
RequestId?: string,
250+
}
251+
/** SDK 的错误格式,其中服务端返回错误码可查看 @see https://cloud.tencent.com/document/product/436/7730 */
252+
interface CosSdkError extends GeneralResult {
247253
/** 错误码 */
248254
code: string,
249255
/** 错误信息 */
250256
message: string,
251257
/** 错误信息,可能是参数错误、客户端出错、或服务端返回的错误 */
252258
error: string | Error | { Code: string, Message: string },
253259
}
254-
/** 一般接口的返回结果 */
255-
interface GeneralResult {
256-
/** 请求返回的 HTTP 状态码 */
257-
statusCode?: number,
258-
/** 请求返回的 header 字段 */
259-
headers?: Headers,
260-
}
260+
/** 回调的错误格式,其中服务端返回错误码可查看 @see https://cloud.tencent.com/document/product/436/7730 */
261+
type CosError = null | CosSdkError;
262+
/** 存储桶操作接口的公共参数 */
261263
interface BucketParams {
262264
/** 存储桶的名称,格式为<bucketname-appid>,例如examplebucket-1250000000 */
263265
Bucket: Bucket,
@@ -266,6 +268,7 @@ declare namespace COS {
266268
/** 请求时带上的 Header 字段 */
267269
Headers?: Headers,
268270
}
271+
/** 对象操作接口的公共参数 */
269272
interface ObjectParams {
270273
/** 存储桶的名称,格式为<bucketname-appid>,例如examplebucket-1250000000 */
271274
Bucket: Bucket,

sdk/base.js

Lines changed: 23 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -3538,52 +3538,34 @@ function _submitRequest(params, callback) {
35383538
chunkList.push(chunk);
35393539
};
35403540
var endHandler = function () {
3541-
var json;
35423541
try {
3543-
var body = Buffer.concat(chunkList);
3542+
var bodyBuf = Buffer.concat(chunkList);
35443543
} catch (e) {
35453544
cb(util.error(e));
35463545
return;
35473546
}
3548-
var bodyStr = body.toString();
3549-
var createBodyError = function (err, json) {
3550-
var cosError = json && json.Error;
3551-
if (cosError) {
3552-
cosError = util.error(err, {
3553-
code: cosError.Code,
3554-
message: cosError.Message,
3555-
error: cosError,
3556-
RequestId: cosError.RequestId,
3557-
Scope: params.Scope,
3558-
});
3559-
} else if (response.statusCode) {
3560-
cosError = util.error(err, {
3561-
code: response.statusCode,
3562-
message: response.statusMessage
3563-
});
3564-
} else {
3565-
cosError = util.error(err, {
3566-
message: response.statusMessage || 'statusCode error'
3567-
});
3568-
}
3569-
return cosError;
3570-
};
3571-
if (statusSuccess) {
3572-
if (rawBody) { // 不对 body 进行转换,body 直接挂载返回
3573-
cb(null, {body: body});
3574-
} else if (body.length) {
3575-
json = xml2json(body.toString());
3576-
if (json && json.Error) {
3577-
cb(createBodyError(new Error(), json));
3578-
} else {
3579-
cb(null, json);
3580-
}
3581-
} else {
3582-
cb(null, {});
3583-
}
3584-
} else {
3585-
bodyStr && (json = xml2json(bodyStr));
3586-
cb(createBodyError(new Error(), json))
3547+
var body = bodyBuf.toString();
3548+
3549+
// 不对 body 进行转换,body 直接挂载返回
3550+
if (rawBody && statusSuccess) return cb(null, {body: bodyBuf});
3551+
3552+
// 解析 xml body
3553+
var json = {};
3554+
try {
3555+
json = body && body.indexOf('<') > -1 && body.indexOf('>') > -1 && util.xml2json(body) || {};
3556+
} catch (e) {
3557+
}
3558+
3559+
// 处理返回值
3560+
var xmlError = json && json.Error;
3561+
if (statusSuccess) { // 正确返回,状态码 2xx 时,body 不会有 Error
3562+
cb(null, json);
3563+
} else if (xmlError) { // 正常返回了 xml body,且有 Error 节点
3564+
cb(util.error(new Error(xmlError.Message), {code: xmlError.Code, error: xmlError}));
3565+
} else if (statusCode) { // 有错误的状态码
3566+
cb(util.error(new Error(response.statusMessage), {code: '' + statusCode}));
3567+
} else if (statusCode) { // 无状态码,或者获取不到状态码
3568+
cb(util.error(new Error('statusCode error')));
35873569
}
35883570
chunkList = null;
35893571
};

sdk/util.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@ var apiWrapper = function (apiName, apiFn) {
398398
// 代理回调函数
399399
var formatResult = function (result) {
400400
if (result && result.headers) {
401+
result.headers['x-cos-request-id'] && (result.RequestId = result.headers['x-cos-request-id']);
401402
result.headers['x-cos-version-id'] && (result.VersionId = result.headers['x-cos-version-id']);
402403
result.headers['x-cos-delete-marker'] && (result.DeleteMarker = result.headers['x-cos-delete-marker']);
403404
}

test/test.js

Lines changed: 45 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -264,19 +264,19 @@ group('auth check', function () {
264264
});
265265
});
266266

267-
group('getBucket()', function () {
267+
group('getBucket(),listObjectVersions', function () {
268268
test('正常获取 bucket 里的文件列表', function (done, assert) {
269269
prepareBucket().then(function () {
270270
cos.getBucket({
271271
Bucket: config.Bucket,
272272
Region: config.Region
273273
}, function (err, data) {
274-
assert.equal(true, data.Name === BucketLongName);
275-
assert.equal(data.Contents.constructor, Array);
274+
assert.ok(data.Name === BucketLongName);
275+
assert.ok(data.Contents.constructor, Array);
276276
done();
277277
});
278278
}).catch(function () {
279-
assert.fail();
279+
assert.ok(false);
280280
done();
281281
});
282282
});
@@ -286,12 +286,12 @@ group('getBucket()', function () {
286286
Bucket: config.Bucket,
287287
Region: config.Region
288288
}, function (err, data) {
289-
assert.equal(true, data.Name === BucketLongName);
290-
assert.equal(data.Versions.constructor, Array);
289+
assert.ok(data.Name === BucketLongName);
290+
assert.ok(data.Versions.constructor === Array);
291291
done();
292292
});
293293
}).catch(function () {
294-
assert.fail();
294+
assert.ok(false);
295295
done();
296296
});
297297
});
@@ -396,6 +396,7 @@ group('sliceUploadFile() 完整上传文件', function () {
396396
}, 1000);
397397
}
398398
if (paused && restarted) {
399+
if (info.percent === 0) return;
399400
assert.ok(info.percent > 0.3, '暂停和重试成功');
400401
cos.cancelTask(TaskId);
401402
fs.unlinkSync(filePath);
@@ -411,7 +412,6 @@ group('sliceUploadFile() 完整上传文件', function () {
411412
var filename = '10m.zip';
412413
var filePath = createFileSync(path.resolve(__dirname, filename), 1024 * 1024 * 10);
413414
var paused = false;
414-
var restarted = false;
415415
cos.abortUploadTask({
416416
Bucket: config.Bucket,
417417
Region: config.Region,
@@ -604,8 +604,8 @@ group('headBucket()', function () {
604604
Bucket: config.Bucket,
605605
Region: config.Region
606606
}, function (err, data) {
607-
assert.equal(true, data.Name === BucketLongName, '能列出 bucket');
608-
assert.equal(data.Contents.constructor, Array, '正常获取 bucket 里的文件列表');
607+
assert.ok(data.Name === BucketLongName, '能列出 bucket');
608+
assert.ok(data.Contents.constructor === Array, '正常获取 bucket 里的文件列表');
609609
done();
610610
});
611611
});
@@ -1083,6 +1083,8 @@ group('sliceCopyFile()', function () {
10831083
delete data2.headers['etag'];
10841084
delete data1.ETag;
10851085
delete data2.ETag;
1086+
delete data1.RequestId;
1087+
delete data2.RequestId;
10861088
assert.ok(comparePlainObject(data1, data2));
10871089
done();
10881090
});
@@ -1130,6 +1132,10 @@ group('sliceCopyFile()', function () {
11301132
delete data2.headers['last-modified'];
11311133
delete data1.headers['date'];
11321134
delete data2.headers['date'];
1135+
delete data1.ETag;
1136+
delete data2.ETag;
1137+
delete data1.RequestId;
1138+
delete data2.RequestId;
11331139
assert.ok(comparePlainObject(data1, data2));
11341140
done();
11351141
});
@@ -1194,7 +1200,7 @@ group('deleteMultipleObject', function () {
11941200
Region: config.Region,
11951201
Objects: [
11961202
{Key: '1.txt'},
1197-
{Key: '2.txt'}
1203+
{Key: '2.txt'},
11981204
],
11991205
}, function (err, data) {
12001206
assert.ok(data.Deleted.length === 2);
@@ -1840,9 +1846,14 @@ group('BucketPolicy', function () {
18401846
"name/cos:AbortMultipartUpload",
18411847
"name/cos:AppendObject"
18421848
],
1843-
"resource": ["qcs::cos:" + config.Region + ":uid/" + AppId + ":" + BucketLongName + ".cos." + config.Region + ".myqcloud.com//" + AppId + "/" + BucketShortName + "/" + Prefix + "/*"] // 1250000000 是 appid
1849+
"resource": ["qcs::cos:" + config.Region + ":uid/" + AppId + ":" + BucketLongName + "//" + AppId + "/" + BucketShortName + "/" + Prefix + "/*"] // 1250000000 是 appid
18441850
}]
18451851
};
1852+
var getRes = function (s) {
1853+
var t = s && s[0];
1854+
var res = t && t.resource && t.resource[0];
1855+
return res;
1856+
};
18461857
test('putBucketPolicy(),getBucketPolicy()', function (done, assert) {
18471858
cos.putBucketPolicy({
18481859
Bucket: config.Bucket,
@@ -1854,7 +1865,7 @@ group('BucketPolicy', function () {
18541865
Bucket: config.Bucket,
18551866
Region: config.Region
18561867
}, function (err, data) {
1857-
assert.ok(Policy, data.Policy);
1868+
assert.ok(getRes(Policy.statement) === getRes(data.Policy.Statement));
18581869
done();
18591870
});
18601871
});
@@ -1870,7 +1881,7 @@ group('BucketPolicy', function () {
18701881
Bucket: config.Bucket,
18711882
Region: config.Region
18721883
}, function (err, data) {
1873-
assert.ok(Policy, data.Policy);
1884+
assert.ok(getRes(Policy.statement) === getRes(data.Policy.Statement));
18741885
done();
18751886
});
18761887
});
@@ -2647,7 +2658,6 @@ group('Cache-Control', function () {
26472658
Region: config.Region,
26482659
Key: '1mb.zip',
26492660
}, function (err, data) {
2650-
console.log(data.headers['cache-control']);
26512661
assert.ok(data.headers['cache-control'] === 'no-cache' || data.headers['cache-control'] === 'no-cache, max-age=259200', 'cache-control 正确');
26522662
fs.unlinkSync(filePath);
26532663
done();
@@ -2776,14 +2786,14 @@ group('BucketInventory', function () {
27762786
Region: config.Region,
27772787
Id: InventoryConfiguration.Id,
27782788
InventoryConfiguration: InventoryConfiguration
2779-
}, function(err, data) {
2789+
}, function (err, data) {
27802790
assert.ok(!err);
27812791

27822792
cos.getBucketInventory({
27832793
Bucket: config.Bucket,
27842794
Region: config.Region,
27852795
Id: InventoryConfiguration.Id
2786-
}, function(err, data) {
2796+
}, function (err, data) {
27872797
assert.ok(comparePlainObject(InventoryConfiguration, data.InventoryConfiguration));
27882798
done();
27892799
});
@@ -2813,7 +2823,7 @@ group('BucketInventory', function () {
28132823
Region: config.Region,
28142824
Id: InventoryConfigurationNoEncryption.Id,
28152825
InventoryConfiguration: InventoryConfigurationNoEncryption
2816-
}, function(err, data) {
2826+
}, function (err, data) {
28172827
assert.ok(!err);
28182828

28192829
cos.getBucketInventory({
@@ -2832,7 +2842,7 @@ group('BucketInventory', function () {
28322842
Bucket: config.Bucket,
28332843
Region: config.Region,
28342844
Id: InventoryConfiguration.Id
2835-
}, function(err, data) {
2845+
}, function (err, data) {
28362846
assert.ok(!err);
28372847
cos.getBucketInventory({
28382848
Bucket: config.Bucket,
@@ -2930,9 +2940,11 @@ group('Content-Type: false Bug', function () {
29302940
});
29312941
});
29322942

2933-
var tagging2str = (obj) => {
2943+
var tagging2str = function (obj) {
29342944
var arr = [];
2935-
obj.forEach(v => arr.push(v.Key + '=' + encodeURIComponent(v.Value)))
2945+
obj.forEach(function (v) {
2946+
arr.push(v.Key + '=' + encodeURIComponent(v.Value));
2947+
})
29362948
return arr.join('&');
29372949
}
29382950
group('上传带 tagging', function () {
@@ -3125,6 +3137,17 @@ group('Promise', function () {
31253137
});
31263138
});
31273139

3140+
test('headBucket callback', function (done, assert) {
3141+
var res = cos.headBucket({
3142+
Bucket: config.Bucket,
3143+
Region: config.Region,
3144+
}, function (err, data) {
3145+
assert.ok(!err && data);
3146+
done();
3147+
});
3148+
assert.ok(!res);
3149+
});
3150+
31283151
test('Promise() getObjectUrl', function (done, assert) {
31293152
var res = cos.getObjectUrl({
31303153
Bucket: config.Bucket,
@@ -3174,7 +3197,7 @@ group('Promise', function () {
31743197
});
31753198

31763199
group('Query 的键值带有特殊字符', function () {
3177-
test('getAuth()', function (done, assert) {
3200+
test('getAuth() 特殊字符', function (done, assert) {
31783201
var content = Date.now().toString();
31793202
var key = '1.txt';
31803203
cos.putObject({

0 commit comments

Comments
 (0)