diff --git a/es5/client.js b/es5/client.js index 05109e2..9d11677 100644 --- a/es5/client.js +++ b/es5/client.js @@ -30,6 +30,7 @@ function getServiceName(serviceName, qualifier) { if (qualifier) { return `${serviceName}.${qualifier}`; } + return serviceName; } @@ -106,7 +107,7 @@ var Client = function () { var _ref = _asyncToGenerator( /*#__PURE__*/_regenerator2.default.mark(function _callee(method, path, query, body) { var headers = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {}; var opts = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : {}; - var url, postBody, buff, digest, md5, queriesToSign, signature, response, responseBody, contentType, code, requestid, err; + var url, postBody, buff, digest, md5, queriesToSign, signature, response, responseBody, contentType, code, requestid, errMsg, err; return _regenerator2.default.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { @@ -211,25 +212,31 @@ var Client = function () { case 33: if (!(response.statusCode < 200 || response.statusCode >= 300)) { - _context.next = 40; + _context.next = 41; break; } code = response.statusCode; requestid = response.headers['x-fc-request-id']; - err = new Error(`${method} ${path} failed with ${code}. requestid: ${requestid}, message: ${responseBody.ErrorMessage}.`); + + if (responseBody.ErrorMessage) { + errMsg = responseBody.ErrorMessage; + } else { + errMsg = responseBody.errorMessage; + } + err = new Error(`${method} ${path} failed with ${code}. requestid: ${requestid}, message: ${errMsg}.`); err.name = `FC${responseBody.ErrorCode}Error`; err.code = responseBody.ErrorCode; throw err; - case 40: + case 41: return _context.abrupt('return', { 'headers': response.headers, 'data': responseBody }); - case 41: + case 42: case 'end': return _context.stop(); } @@ -579,7 +586,7 @@ var Client = function () { * @param {String} serviceName * @param {String} functionName * @param {Object} event event信息 - * @param {Object} headers + * @param {Object} headers * @param {String} qualifier * @return {Promise} 返回 Object(包含headers和data属性[返回Function的执行结果]) */ @@ -705,16 +712,16 @@ var Client = function () { } /** - * 创建CustomDomain - * - * Options: - * - protocol - * - routeConfig - * - * @param {String} domainName 域名 - * @param {Object} options 选项,optional - * @return {Promise} 返回 Object(包含headers和data属性[CustomDomainResponse]) - */ + * 创建CustomDomain + * + * Options: + * - protocol + * - routeConfig + * + * @param {String} domainName 域名 + * @param {Object} options 选项,optional + * @return {Promise} 返回 Object(包含headers和data属性[CustomDomainResponse]) + */ }, { key: 'createCustomDomain', @@ -766,10 +773,10 @@ var Client = function () { * 更新CustomDomain信息 * * Options: - * - protocol + * - protocol * - routeConfig * - * @param {String} domainName + * @param {String} domainName * @param {Object} options 选项,optional * @return {Promise} 返回 Object(包含headers和data属性[Service 信息]) */ @@ -801,7 +808,7 @@ var Client = function () { /** * 创建 version - * + * * @param {String} serviceName * @param {String} description * @param {Object} headers @@ -820,16 +827,16 @@ var Client = function () { /** * 列出 version - * + * * Options: * - limit * - nextToken * - startKey * - direction - * - * @param {String} serviceName - * @param {Object} options - * @param {Object} headers + * + * @param {String} serviceName + * @param {Object} options + * @param {Object} headers * @return {Promise} 返回 Object(包含headers和data属性[Version 信息]) */ @@ -844,10 +851,10 @@ var Client = function () { /** * 删除 version - * - * @param {String} serviceName - * @param {String} versionId - * @param {Object} headers + * + * @param {String} serviceName + * @param {String} versionId + * @param {Object} headers * @return {Promise} 返回 Object(包含headers和data属性) */ @@ -861,16 +868,16 @@ var Client = function () { /** * 创建 Alias - * + * * Options: * - description * - additionalVersionWeight - * - * @param {String} serviceName - * @param {String} aliasName - * @param {String} versionId - * @param {Object} options - * @param {Object} headers + * + * @param {String} serviceName + * @param {String} aliasName + * @param {String} versionId + * @param {Object} options + * @param {Object} headers * @return {Promise} 返回 Object(包含headers和data属性) */ @@ -888,10 +895,10 @@ var Client = function () { /** * 删除 Alias - * - * @param {String} serviceName - * @param {String} aliasName - * @param {String} headers + * + * @param {String} serviceName + * @param {String} aliasName + * @param {String} headers * @return {Promise} 返回 Object(包含headers和data属性) */ @@ -905,16 +912,16 @@ var Client = function () { /** * 列出 alias - * + * * Options: * - limit * - nextToken * - prefix * - startKey - * - * @param {String} serviceName - * @param {Object} options - * @param {Object} headers + * + * @param {String} serviceName + * @param {Object} options + * @param {Object} headers * @return {Promise} 返回 Object(包含headers和data属性) */ @@ -929,10 +936,10 @@ var Client = function () { /** * 获得 alias - * - * @param {String} serviceName - * @param {String} aliasName - * @param {Object} headers + * + * @param {String} serviceName + * @param {String} aliasName + * @param {Object} headers * @return {Promise} 返回 Object(包含headers和data属性) */ @@ -946,16 +953,16 @@ var Client = function () { /** * 更新 alias - * + * * Options: * - description * - additionalVersionWeight - * - * @param {String} serviceName - * @param {String} aliasName - * @param {String} versionId - * @param {Object} options - * @param {Object} headers + * + * @param {String} serviceName + * @param {String} aliasName + * @param {String} versionId + * @param {Object} options + * @param {Object} headers * @return {Promise} 返回 Object(包含headers和data属性) */ @@ -973,11 +980,11 @@ var Client = function () { /** * 给fc资源打tag - * + * * @param {String} resourceArn Resource ARN. Either full ARN or partial ARN. * @param {Object} tags A list of tag keys. At least 1 tag is required. At most 20. Tag key is required, but tag value is optional. - * @param {Object} options - * @param {Object} headers + * @param {Object} options + * @param {Object} headers * @return {Promise} 返回 Object(包含headers和data属性) */ @@ -994,15 +1001,15 @@ var Client = function () { } /** - * 给fc资源取消tag - * - * @param {String} resourceArn Resource ARN. Either full ARN or partial ARN. - * @param {Object} tagkeys A list of tag keys. At least 1 tag key is required if all=false. At most 20. - * @param {Boolean} all Remove all tags at once. Default value is false. Accept value: true or false. - * @param {Object} options - * @param {Object} headers - * @return {Promise} 返回 Object(包含headers和data属性) - */ + * 给fc资源取消tag + * + * @param {String} resourceArn Resource ARN. Either full ARN or partial ARN. + * @param {Object} tagkeys A list of tag keys. At least 1 tag key is required if all=false. At most 20. + * @param {Boolean} all Remove all tags at once. Default value is false. Accept value: true or false. + * @param {Object} options + * @param {Object} headers + * @return {Promise} 返回 Object(包含headers和data属性) + */ }, { key: 'untagResource', @@ -1018,12 +1025,12 @@ var Client = function () { } /** - * 获取某个资源的所有tag - * - * @param {Object} options - * @param {Object} headers - * @return {Promise} 返回 Object(包含headers和data属性) - */ + * 获取某个资源的所有tag + * + * @param {Object} options + * @param {Object} headers + * @return {Promise} 返回 Object(包含headers和data属性) + */ }, { key: 'getResourceTags', @@ -1054,6 +1061,65 @@ var Client = function () { return this.get('/reservedCapacities', options, headers); } + /** + * 获取账号下的 provisionConfigs 列表 + * + * Options: + * - limit + * - nextToken + * - serviceName + * - qualifier + * + * @param {Object} options 选项,optional + * @return {Promise} 返回 Object(包含 headers 和 data 属性[provisionConfigs 列表]) + */ + + }, { + key: 'listProvisionConfigs', + value: function listProvisionConfigs() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var headers = arguments[1]; + + return this.get('/provision-configs', options, headers); + } + + /** + * 获取单个函数的 provisionConfig + * + * @param {String} serviceName + * @param {String} functionName + * @param {Object} headers + * @param {String} qualifier 可选 + * @return {Promise} 返回 Object(包含 headers 和 data 属性[provisionConfig 信息]) + */ + + }, { + key: 'getProvisionConfig', + value: function getProvisionConfig(serviceName, functionName, qualifier) { + var headers = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + + return this.get(`/services/${getServiceName(serviceName, qualifier)}/functions/${functionName}/provision-config`, null, headers); + } + + /** + * 更新单个函数的 provisionConfig + * + * @param {String} serviceName + * @param {String} functionName + * @param {Object} headers + * @param {String} qualifier 可选 + * @return {Promise} 返回 Object(包含 headers 和 data 属性[provisionConfig 信息]) + */ + + }, { + key: 'putProvisionConfig', + value: function putProvisionConfig(serviceName, functionName, qualifier) { + var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + var headers = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {}; + + return this.put(`/services/${getServiceName(serviceName, qualifier)}/functions/${functionName}/provision-config`, options, headers); + } + /** * 获得Header 签名 * @@ -1077,4 +1143,4 @@ var Client = function () { return Client; }(); -module.exports = Client; \ No newline at end of file +module.exports = Client; diff --git a/lib/client.js b/lib/client.js index ca76ba3..9024eac 100644 --- a/lib/client.js +++ b/lib/client.js @@ -157,7 +157,13 @@ class Client { if (response.statusCode < 200 || response.statusCode >= 300) { const code = response.statusCode; const requestid = response.headers['x-fc-request-id']; - const err = new Error(`${method} ${path} failed with ${code}. requestid: ${requestid}, message: ${responseBody.ErrorMessage}.`); + var errMsg; + if (responseBody.ErrorMessage) { + errMsg = responseBody.ErrorMessage; + } else { + errMsg = responseBody.errorMessage; + } + const err = new Error(`${method} ${path} failed with ${code}. requestid: ${requestid}, message: ${errMsg}.`); err.name = `FC${responseBody.ErrorCode}Error`; err.code = responseBody.ErrorCode; throw err; @@ -805,7 +811,7 @@ class Client { * @param {String} qualifier 可选 * @return {Promise} 返回 Object(包含 headers 和 data 属性[provisionConfig 信息]) */ - getProvisionConfig(serviceName, functionName, headers = {}, qualifier) { + getProvisionConfig(serviceName, functionName, qualifier, headers = {}, ) { return this.get(`/services/${getServiceName(serviceName, qualifier)}/functions/${functionName}/provision-config`, null, headers); } @@ -818,7 +824,7 @@ class Client { * @param {String} qualifier 可选 * @return {Promise} 返回 Object(包含 headers 和 data 属性[provisionConfig 信息]) */ - putProvisionConfig(serviceName, functionName, options = {}, headers = {}, qualifier) { + putProvisionConfig(serviceName, functionName, qualifier, options = {}, headers = {}) { return this.put(`/services/${getServiceName(serviceName, qualifier)}/functions/${functionName}/provision-config`, options, headers); } @@ -839,4 +845,4 @@ class Client { } } -module.exports = Client; +module.exports = Client; \ No newline at end of file diff --git a/test/client.test.js b/test/client.test.js index f2340a0..91c28c7 100644 --- a/test/client.test.js +++ b/test/client.test.js @@ -22,7 +22,9 @@ describe('client test', function () { b: 'xyz', 'foo-bar': '123 ~ xyz-a' }; - var signature = FunctionComputeClient.getSignature(ACCOUNT_ID, ACCESS_KEY_SECRET, 'GET', '/hello/world', { date: 'today' }, queries); + var signature = FunctionComputeClient.getSignature(ACCOUNT_ID, ACCESS_KEY_SECRET, 'GET', '/hello/world', { + date: 'today' + }, queries); expect(signature).to.be.ok(); expect(signature).to.contain(`FC ${ACCOUNT_ID}:`); }); @@ -184,6 +186,8 @@ describe('client test', function () { await client.deleteFunction(service.serviceName, fun.functionName); } await client.deleteService(service.serviceName); + await client.deleteFunction('fc-nodejs-sdk-unit-test', 'testProvisionConfig'); + await client.deleteService('fc-nodejs-sdk-unit-test'); } } }); @@ -370,7 +374,9 @@ describe('client test', function () { }); it('invokeFunction with rawBuf=false should return string', async function () { - const response = await client.invokeFunction(serviceName, functionName, Buffer.from('world'), {}, 'LATEST', {rawBuf:false}); + const response = await client.invokeFunction(serviceName, functionName, Buffer.from('world'), {}, 'LATEST', { + rawBuf: false + }); expect(response.data).a('string'); expect(response.data).to.be('hello world'); }); @@ -390,7 +396,9 @@ describe('client test', function () { expect(func.data).to.be.ok(); expect(func.data).to.have.property('functionName', functionWithBufResp); - const response = await client.invokeFunction(serviceName, functionWithBufResp, Buffer.from('world'), {}, 'LATEST', {rawBuf: true}); + const response = await client.invokeFunction(serviceName, functionWithBufResp, Buffer.from('world'), {}, 'LATEST', { + rawBuf: true + }); expect(response.data).an(Buffer); expect(response.data.toString()).to.be('world'); }); @@ -410,9 +418,13 @@ describe('client test', function () { expect(func.data).to.be.ok(); expect(func.data).to.have.property('functionName', functionWithHandledErr); - const response = await client.invokeFunction(serviceName, functionWithHandledErr, Buffer.from('world'), {}, 'LATEST', {rawBuf: true}); + const response = await client.invokeFunction(serviceName, functionWithHandledErr, Buffer.from('world'), {}, 'LATEST', { + rawBuf: true + }); expect(response.data).not.an(Buffer); - expect(JSON.stringify(response.data)).to.be(JSON.stringify({ 'errorMessage': 'This is a handled error' })); + expect(JSON.stringify(response.data)).to.be(JSON.stringify({ + 'errorMessage': 'This is a handled error' + })); }); it('invokeFunction with unhandled error should decode with utf8', async function () { @@ -430,9 +442,13 @@ describe('client test', function () { expect(func.data).to.be.ok(); expect(func.data).to.have.property('functionName', functionWithUnhandledErr); - const response = await client.invokeFunction(serviceName, functionWithUnhandledErr, Buffer.from('world'), {}, 'LATEST', {rawBuf: true}); + const response = await client.invokeFunction(serviceName, functionWithUnhandledErr, Buffer.from('world'), {}, 'LATEST', { + rawBuf: true + }); expect(response.data).not.an(Buffer); - expect(JSON.stringify(response.data)).contain(JSON.stringify({ 'errorMessage': 'Process exited unexpectedly before completing request' }).slice(0,-2)); + expect(JSON.stringify(response.data)).contain(JSON.stringify({ + 'errorMessage': 'Process exited unexpectedly before completing request' + }).slice(0, -2)); }); it('invokeFunction async should ok', async function () { @@ -597,12 +613,14 @@ describe('client test', function () { }); after(async function () { + await client.deleteTrigger(serviceName, 'http_trigger_with_function_error', 'http-trigger'); + await client.deleteFunction(serviceName, 'http_trigger_with_function_error'); await cleanupResources(client, serviceName, functionName, triggerName); }); it('createTrigger should be ok', async function () { const triggerConfig = { - 'authType': 'function', // `function` level here to make sure working well for signature. + 'authType': 'function', // `function` level here to make sure working well for signature. 'methods': ['GET', 'POST', 'PUT'] }; await createTrigger(client, serviceName, functionName, triggerName, 'http', triggerConfig); @@ -642,6 +660,40 @@ describe('client test', function () { var body = JSON.parse(resp.data); expect(body).to.have.property('method', 'GET'); }); + + it('http trigger with function error passing through should be ok', async function () { + const functionName = 'http_trigger_with_function_error'; + const handlerName = 'main.http_function_err_handler'; + const func = await client.createFunction(serviceName, { + functionName: functionName, + description: 'function desc', + memorySize: 128, + handler: handlerName, + runtime: 'nodejs6', + timeout: 10, + code: { + zipFile: fs.readFileSync(path.join(__dirname, 'figures/test.zip'), 'base64') + } + }); + expect(func.data).to.be.ok(); + expect(func.data).to.have.property('functionName', functionName); + + const triggerConfig = { + 'authType': 'anonymous', + 'methods': ['GET', 'POST', 'PUT'] + }; + + await createTrigger(client, serviceName, functionName, triggerName, 'http', triggerConfig); + + const funcPath = `/proxy/${serviceName}/${functionName}/action`; + try { + await client.get(funcPath); + } catch (ex) { + expect(ex.name).to.be('FCundefinedError'); + expect(ex.message).to.match(/GET .* failed with 502\. requestid: .{36}, message: Process exited unexpectedly before completing request.*/); + } + }); + }); describe('oss trigger should be ok', function () { @@ -746,13 +798,11 @@ describe('client test', function () { it('updateCustomDomain should be ok', async function () { const customDomain = await client.updateCustomDomain(domainName, { routeConfig: { - routes: [ - { - path: '/', - serviceName: 's1', - functionName: 'f1', - } - ] + routes: [{ + path: '/', + serviceName: 's1', + functionName: 'f1', + }] }, }); expect(customDomain.data).to.be.ok(); @@ -803,46 +853,47 @@ describe('client test', function () { }); it('create alias', async function () { - const res = await client.createAlias(serviceName, aliasName, '1', - { - 'description': 'test alias', - 'additionalVersionWeight': { - '1': 1 - } - }); + const res = await client.createAlias(serviceName, aliasName, '1', { + 'description': 'test alias', + 'additionalVersionWeight': { + '1': 1 + } + }); expect(res.data.aliasName).to.be(aliasName); expect(res.data.versionId).to.be('1'); expect(res.data.description).to.be('test alias'); - expect(res.data.additionalVersionWeight).to.eql({ '1': 1 }); + expect(res.data.additionalVersionWeight).to.eql({ + '1': 1 + }); }); it('update alias', async function () { - var res = await client.updateAlias(serviceName, aliasName, null, - { - 'additionalVersionWeight': { - '2': 0.3 - }, - 'description': '' - } - ); + var res = await client.updateAlias(serviceName, aliasName, null, { + 'additionalVersionWeight': { + '2': 0.3 + }, + 'description': '' + }); expect(res.data.aliasName).to.be(aliasName); expect(res.data.versionId).to.be('1'); expect(res.data.description).to.be(''); - expect(res.data.additionalVersionWeight).to.eql({ '2': 0.3 }); + expect(res.data.additionalVersionWeight).to.eql({ + '2': 0.3 + }); - res = await client.updateAlias(serviceName, aliasName, '2', - { - 'additionalVersionWeight': { - '2': 0.5 - } + res = await client.updateAlias(serviceName, aliasName, '2', { + 'additionalVersionWeight': { + '2': 0.5 } - ); + }); expect(res.data.aliasName).to.be(aliasName); expect(res.data.versionId).to.be('2'); expect(res.data.description).to.be(''); - expect(res.data.additionalVersionWeight).to.eql({ '2': 0.5 }); + expect(res.data.additionalVersionWeight).to.eql({ + '2': 0.5 + }); }); it('get alias', async function () { @@ -851,7 +902,9 @@ describe('client test', function () { expect(res.data.aliasName).to.be(aliasName); expect(res.data.versionId).to.be('2'); expect(res.data.description).to.be(''); - expect(res.data.additionalVersionWeight).to.eql({ '2': 0.5 }); + expect(res.data.additionalVersionWeight).to.eql({ + '2': 0.5 + }); }); it('list aliases', async function () { @@ -860,7 +913,9 @@ describe('client test', function () { expect(res.data.aliases).to.length(1); expect(res.data.aliases[0].versionId).to.be('2'); expect(res.data.aliases[0].description).to.be(''); - expect(res.data.aliases[0].additionalVersionWeight).to.eql({ '2': 0.5 }); + expect(res.data.aliases[0].additionalVersionWeight).to.eql({ + '2': 0.5 + }); }); it('delete alias', async function () { @@ -934,7 +989,10 @@ describe('client test', function () { }); it('tagResource should ok', async function () { - await client.tagResource(`services/${tagServiceName}`, {k1:'v1', k2:'v2'}); + await client.tagResource(`services/${tagServiceName}`, { + k1: 'v1', + k2: 'v2' + }); const resp = await client.getResourceTags({ 'resourceArn': `services/${tagServiceName}` }); @@ -943,7 +1001,7 @@ describe('client test', function () { expect(resp.data.tags.k1).to.be('v1'); expect(resp.data.tags.k2).to.be('v2'); var lresp = await client.listServices({ - tags:{ + tags: { k1: 'v1', k2: 'v2', } @@ -996,7 +1054,7 @@ describe('client test', function () { const elem = response.data.reservedCapacities[i]; expect(elem.instanceId.length).to.be.equal(22); expect(elem.cu).to.be.above(0); - expect(elem.Deadline>elem.CreatedTime).to.be.true; + expect(elem.Deadline > elem.CreatedTime).to.be.true; expect(elem).to.have.property('lastModifiedTime'); expect(elem).to.have.property('isRefunded'); } @@ -1010,17 +1068,30 @@ describe('client test', function () { region: 'cn-shanghai' }); const functionName = 'testProvisionConfig'; + const aliasName = 'prod'; before(async function () { await createServiceAndFunction(client, serviceName, functionName, 'main.handler'); + await client.publishVersion(serviceName, 'test version 1'); + await client.createAlias(serviceName, aliasName, '1', { + 'description': 'test alias', + 'additionalVersionWeight': { + '1': 1 + } + }); }); after(async function () { + await client.putProvisionConfig(serviceName, functionName, aliasName, { + target: 0, + }); + await client.deleteVersion(serviceName, '1'); + await client.deleteAlias(serviceName, aliasName); await cleanupResources(client, serviceName, functionName); }); - it('putProvisionConfigs should be ok', async function() { - const response = await client.putProvisionConfig(serviceName, functionName, { + it('putProvisionConfigs should be ok', async function () { + const response = await client.putProvisionConfig(serviceName, functionName, aliasName, { target: 1, }); expect(response.data).to.be.ok(); @@ -1028,24 +1099,25 @@ describe('client test', function () { expect(response.data.resource).to.be.ok(); }); - it('getProvisionConfig should be ok', async function() { - const response = await client.getProvisionConfig(serviceName, functionName); + it('getProvisionConfig should be ok', async function () { + const response = await client.getProvisionConfig(serviceName, functionName, aliasName); expect(response.data).to.be.ok(); expect(response.data.target).to.be.equal(1); - expect(response.data.current).to.be.equal(1); expect(response.data.resource).to.be.ok(); }); it('listProvisionConfigs should ok', async function () { - const response = await client.listProvisionConfigs(); + const response = await client.listProvisionConfigs({ + 'serviceName': serviceName, + 'qualifier': aliasName, + }); expect(response.data).to.be.ok(); expect(response.data.provisionConfigs).to.be.ok(); for (var i = 0; i < response.data.provisionConfigs.length; i++) { const elem = response.data.provisionConfigs[i]; expect(elem.target).to.be.equal(1); - expect(elem.current).to.be.equal(1); expect(elem.resource).to.be.ok(); } }); }); -}); +}); \ No newline at end of file diff --git a/test/figures/main.js b/test/figures/main.js index a3ec3bc..dad0d3d 100644 --- a/test/figures/main.js +++ b/test/figures/main.js @@ -45,3 +45,9 @@ exports.http_handler = function (request, response, context) { response.send(JSON.stringify(retBody)); }); }; + +module.exports.http_function_err_handler = function (request, response, context) { + console.log(context.toSting()); + response.send(new Buffer('hello world')); + +}; \ No newline at end of file