alibabacloud-gateway-fc/main.tea (381 lines of code) (raw):

import SPI; import Credential; import Util; import OpenApiUtil; import EndpointUtil; import EncodeUtil; import SignatureUtil; import String; import Map; import Array; extends SPI; init() { super(); } async function modifyConfiguration(context: SPI.InterceptorContext, attributeMap: SPI.AttributeMap): void { var request = context.request; var config = context.configuration; config.endpoint = getEndpoint(request.productId, config.regionId, config.endpointRule, config.network, config.suffix, config.endpointMap, config.endpoint); } async function modifyRequest(context: SPI.InterceptorContext, attributeMap: SPI.AttributeMap): void { var config = context.configuration; if (!String.hasSuffix(config.endpoint, 'aliyuncs.com')) { signRequestForFc(context); } else { signRequestForPop(context); } } async function modifyResponse(context: SPI.InterceptorContext, attributeMap: SPI.AttributeMap): void { var request = context.request; var config = context.configuration; var response = context.response; if (Util.is4xx(response.statusCode) || Util.is5xx(response.statusCode)) { if (String.hasPrefix(config.endpoint, 'fc.') && String.hasSuffix(config.endpoint, '.aliyuncs.com')) { var popRes = Util.readAsJSON(response.body); var popErr = Util.assertAsMap(popRes); throw { code = `${defaultAny(popErr.Code, popErr.code)}`, message = `code: ${response.statusCode}, ${defaultAny(popErr.Message, popErr.message)} request id: ${defaultAny(popErr.RequestID, popErr.RequestId)}`, data = popErr, }; } else { var _headers = Util.assertAsMap(response.headers); var fcRes = Util.readAsJSON(response.body); var fcErr = Util.assertAsMap(fcRes); throw { code = fcErr.ErrorCode, message = `code: ${response.statusCode}, ${fcErr.ErrorMessage} request id: ${_headers.x-fc-request-id}`, data = fcErr, }; } } if (Util.equalString(request.bodyType, 'binary')) { response.deserializedBody = response.body; } else if (Util.equalString(request.bodyType, 'byte')) { var byt = Util.readAsBytes(response.body); response.deserializedBody = byt; } else if (Util.equalString(request.bodyType, 'string')) { var str = Util.readAsString(response.body); response.deserializedBody = str; } else if (Util.equalString(request.bodyType, 'json')) { var obj = Util.readAsJSON(response.body); var res = Util.assertAsMap(obj); response.deserializedBody = res; } else if (Util.equalString(request.bodyType, 'array')) { var arr = Util.readAsJSON(response.body); response.deserializedBody = arr; } else { response.deserializedBody = Util.readAsString(response.body); } } function getEndpoint(productId: string, regionId: string, endpointRule: string, network: string, suffix: string, endpointMap: map[string]string, endpoint: string) throws: string{ if (!Util.empty(endpoint)) { return endpoint; } if (!Util.isUnset(endpointMap) && !Util.empty(endpointMap[regionId])) { return endpointMap[regionId]; } return EndpointUtil.getEndpointRules(productId, regionId, endpointRule, network, suffix); } function defaultAny(inputValue: any, defaultValue: any): any { if (Util.isUnset(inputValue)) { return defaultValue; } return inputValue; } async function signRequestForFc(context: SPI.InterceptorContext): void { var request = context.request; var config = context.configuration; request.headers = { host = config.endpoint, date = Util.getDateUTCString(), accept = 'application/json', user-agent = request.userAgent, ...request.headers }; request.headers.content-type = 'application/json'; if (!Util.isUnset(request.stream)) { var tmp = Util.readAsBytes(request.stream); request.stream = tmp; request.headers.content-type = 'application/octet-stream'; request.headers.content-md5 = EncodeUtil.base64EncodeToString(SignatureUtil.MD5SignForBytes(tmp)); } else { if (!Util.isUnset(request.body)) { if (Util.equalString(request.reqBodyType, 'json')) { var jsonObj = Util.toJSONString(request.body); request.stream = jsonObj; request.headers.content-type = 'application/json'; request.headers.content-md5 = EncodeUtil.base64EncodeToString(SignatureUtil.MD5Sign(jsonObj)); } else { var m = Util.assertAsMap(request.body); var formObj = OpenApiUtil.toForm(m); request.stream = formObj; request.headers.content-type = 'application/x-www-form-urlencoded'; request.headers.content-md5 = EncodeUtil.base64EncodeToString(SignatureUtil.MD5Sign(formObj)); } } } var credential : Credential = request.credential; var accessKeyId = credential.getAccessKeyId(); var accessKeySecret = credential.getAccessKeySecret(); var securityToken = credential.getSecurityToken(); if (!Util.empty(securityToken)) { request.headers.x-fc-security-token = securityToken; } request.headers.Authorization = getAuthorizationForFc(request.pathname, request.method, request.query, request.headers, accessKeyId, accessKeySecret); } async function signRequestForPop(context: SPI.InterceptorContext): void { var request = context.request; var config = context.configuration; request.headers = { host = config.endpoint, x-acs-version = request.version, x-acs-action = request.action, user-agent = request.userAgent, x-acs-date = OpenApiUtil.getTimestamp(), x-acs-signature-nonce = Util.getNonce(), accept = 'application/json', ...request.headers }; var signatureAlgorithm : string = 'ACS3-HMAC-SHA256'; if (!Util.isUnset(request.signatureAlgorithm)) { signatureAlgorithm = request.signatureAlgorithm; } var hashedRequestPayload = EncodeUtil.hexEncode(EncodeUtil.hash(Util.toBytes(''), signatureAlgorithm)); if (!Util.isUnset(request.stream)) { var tmp = Util.readAsBytes(request.stream); hashedRequestPayload = EncodeUtil.hexEncode(EncodeUtil.hash(tmp, signatureAlgorithm)); request.stream = tmp; request.headers.content-type = 'application/octet-stream'; } else { if (!Util.isUnset(request.body)) { if (Util.equalString(request.reqBodyType, 'json')) { var jsonObj = Util.toJSONString(request.body); hashedRequestPayload = EncodeUtil.hexEncode(EncodeUtil.hash(Util.toBytes(jsonObj), signatureAlgorithm)); request.stream = jsonObj; request.headers.content-type = 'application/json; charset=utf-8'; } else { var m = Util.assertAsMap(request.body); var formObj = OpenApiUtil.toForm(m); hashedRequestPayload = EncodeUtil.hexEncode(EncodeUtil.hash(Util.toBytes(formObj), signatureAlgorithm)); request.stream = formObj; request.headers.content-type = 'application/x-www-form-urlencoded'; } } } request.headers.x-acs-content-sha256 = hashedRequestPayload; if (!Util.equalString(request.authType, 'Anonymous')) { var credential : Credential = request.credential; var accessKeyId = credential.getAccessKeyId(); var accessKeySecret = credential.getAccessKeySecret(); var securityToken = credential.getSecurityToken(); if (!Util.empty(securityToken)) { request.headers.x-acs-accesskey-id = accessKeyId; request.headers.x-acs-security-token = securityToken; } request.headers.Authorization = getAuthorizationForPop(request.pathname, request.method, request.query, request.headers, signatureAlgorithm, hashedRequestPayload, accessKeyId, accessKeySecret); } } async function getAuthorizationForFc(pathname: string, method: string, query: map[string]string, headers: map[string]string, ak: string, secret: string): string { var sign = getSignatureForFc(pathname, method, query, headers, secret); return `FC ${ak}:${sign}`; } async function getSignatureForFc(pathname: string, method: string, query: map[string]string, headers: map[string]string, secret: string): string { var resource : string = pathname; var contentMd5 = headers.content-md5; if (Util.isUnset(contentMd5)) { contentMd5 = ''; } var contentType = headers.content-type; if (Util.isUnset(contentType)) { contentType = ''; } var stringToSign : string = ''; var canonicalizedResource = buildCanonicalizedResourceForFc(resource, query); var canonicalizedHeaders = buildCanonicalizedHeadersForFc(headers); stringToSign = `${method}\n${contentMd5}\n${contentType}\n${headers.date}\n${canonicalizedHeaders}${canonicalizedResource}`; return EncodeUtil.base64EncodeToString(SignatureUtil.HmacSHA256Sign(stringToSign, secret)); } async function buildCanonicalizedResourceForFc(pathname: string, query: map[string]string): string { var paths : [string] = String.split(pathname, `?`, 2); var canonicalizedResource : string = paths[0]; var resources : [string] = []; if (Util.equalNumber(Array.size(paths), 2)) { resources = String.split(paths[1], '&', null); } var subResources : [string] = []; var tmp : string = ''; var separator : string = ''; if (!Util.isUnset(query)) { var queryList : [string] = Map.keySet(query); for(var paramName : queryList) { tmp = `${tmp}${separator}${paramName}`; if (!Util.isUnset(query[paramName])) { tmp = `${tmp}=${query[paramName]}`; } separator = ';'; } subResources = String.split(tmp, ';', null); } var result : [string] = Array.concat(subResources, resources); var sortedParams = Array.ascSort(result); if (Util.equalNumber(Array.size(sortedParams), 0)) { return `${canonicalizedResource}\n`; } var subRes = Array.join(sortedParams, '\\n'); return `${canonicalizedResource}\n${subRes}`; } async function buildCanonicalizedHeadersForFc(headers: map[string]string): string { var canonicalizedHeaders : string = ''; var keys = Map.keySet(headers); var sortedHeaders = Array.ascSort(keys); for(var header : sortedHeaders) { if (String.contains(String.toLower(header), 'x-fc-')) { canonicalizedHeaders = `${canonicalizedHeaders}${String.toLower(header)}:${headers[header]}\n`; } } return canonicalizedHeaders; } async function getAuthorizationForPop(pathname: string, method: string, query: map[string]string, headers: map[string]string, signatureAlgorithm: string, payload: string, ak: string, secret: string): string { var signature = getSignatureForPop(pathname, method, query, headers, signatureAlgorithm, payload, secret); var signedHeaders = getSignedHeaders(headers); return `${signatureAlgorithm} Credential=${ak},SignedHeaders=${Array.join(signedHeaders, ';')},Signature=${signature}`; } async function getSignatureForPop(pathname: string, method: string, query: map[string]string, headers: map[string]string, signatureAlgorithm: string, payload: string, secret: string): string { var canonicalURI : string = '/'; if (!Util.empty(pathname)) { canonicalURI = pathname; } var stringToSign : string = ''; var canonicalizedResource = buildCanonicalizedResourceForPop(query); var canonicalizedHeaders = buildCanonicalizedHeadersForPop(headers); var signedHeaders = getSignedHeaders(headers); stringToSign = `${method}\n${canonicalURI}\n${canonicalizedResource}\n${canonicalizedHeaders}\n${Array.join(signedHeaders, ';')}\n${payload}`; var hex = EncodeUtil.hexEncode(EncodeUtil.hash(Util.toBytes(stringToSign), signatureAlgorithm)); stringToSign = `${signatureAlgorithm}\n${hex}`; var signature = Util.toBytes(''); if (String.equals(signatureAlgorithm, 'ACS3-HMAC-SHA256')) { signature = SignatureUtil.HmacSHA256Sign(stringToSign, secret); } else if (String.equals(signatureAlgorithm, 'ACS3-HMAC-SM3')) { signature = SignatureUtil.HmacSM3Sign(stringToSign, secret); } else if (String.equals(signatureAlgorithm, 'ACS3-RSA-SHA256')) { signature = SignatureUtil.SHA256withRSASign(stringToSign, secret); } return EncodeUtil.hexEncode(signature); } async function buildCanonicalizedResourceForPop(query: map[string]string): string { var canonicalizedResource : string = ''; if (!Util.isUnset(query)) { var queryArray : [string] = Map.keySet(query); var sortedQueryArray = Array.ascSort(queryArray); var separator : string = ''; for(var key : sortedQueryArray) { canonicalizedResource = `${canonicalizedResource}${separator}${EncodeUtil.percentEncode(key)}`; if (!Util.empty(query[key])) { canonicalizedResource = `${canonicalizedResource}=${EncodeUtil.percentEncode(query[key])}`; } separator = '&'; } } return canonicalizedResource; } async function buildCanonicalizedHeadersForPop(headers: map[string]string): string { var canonicalizedHeaders : string = ''; var sortedHeaders : [string] = getSignedHeaders(headers); for(var header : sortedHeaders) { canonicalizedHeaders = `${canonicalizedHeaders}${header}:${String.trim(headers[header])}\n`; } return canonicalizedHeaders; } async function getSignedHeaders(headers: map[string]string): [string] { var headersArray : [string] = Map.keySet(headers); var sortedHeadersArray = Array.ascSort(headersArray); var tmp : string = ''; var separator : string = ''; for(var key : sortedHeadersArray) { var lowerKey = String.toLower(key); if (String.hasPrefix(lowerKey, 'x-acs-') || String.equals(lowerKey, 'host') || String.equals(lowerKey, 'content-type')) { if (!String.contains(tmp, lowerKey)) { tmp = `${tmp}${separator}${lowerKey}`; separator = ';'; } } } return String.split(tmp, ';', null); } model HttpRequest = { method: string, path: string, headers?: map[string]any, body?: bytes, reqBodyType?: string } async function signRequest(request: HttpRequest, credential: Credential): map[string]any { var httpRequest : HttpRequest = new HttpRequest{ method = request.method, path = request.path, headers = request.headers, body = request.body, reqBodyType = request.reqBodyType }; httpRequest.headers.date = Util.getDateUTCString(); httpRequest.headers.accept = 'application/json'; httpRequest.headers.content-type = 'application/json'; if (!Util.isUnset(request.body)) { if (Util.equalString(request.reqBodyType, 'json')) { httpRequest.headers.content-type = 'application/json'; } else if (Util.equalString(request.reqBodyType, 'form')) { httpRequest.headers.content-type = 'application/x-www-form-urlencoded'; } else if (Util.equalString(request.reqBodyType, 'binary')) { httpRequest.headers.content-type = 'application/octet-stream'; } } var accessKeyId = credential.getAccessKeyId(); var accessKeySecret = credential.getAccessKeySecret(); var securityToken = credential.getSecurityToken(); if (!Util.empty(securityToken)) { httpRequest.headers.x-fc-security-token = securityToken; } var resource : string = request.path; var contentMd5 = httpRequest.headers.content-md5; if (Util.isUnset(contentMd5)) { contentMd5 = ''; } var contentType = httpRequest.headers.content-type; if (Util.isUnset(contentType)) { contentType = ''; } var stringToSign : string = ''; var canonicalizedResource = buildCanonicalizedResource(resource); var canonicalizedHeaders = buildCanonicalizedHeaders(httpRequest.headers); stringToSign = `${request.method}\n${Util.toJSONString(contentMd5)}\n${Util.toJSONString(contentType)}\n${Util.toJSONString(httpRequest.headers.date)}\n${canonicalizedHeaders}${canonicalizedResource}`; var signature = EncodeUtil.base64EncodeToString(SignatureUtil.HmacSHA256Sign(stringToSign, accessKeySecret)); httpRequest.headers.Authorization = `FC ${accessKeyId}:${signature}`; return httpRequest.headers; } async function buildCanonicalizedResource(pathname: string): string { var paths : [string] = String.split(pathname, `?`, 2); var canonicalizedResource : string = paths[0]; var resources : [string] = []; if (Util.equalNumber(Array.size(paths), 2)) { resources = String.split(paths[1], '&', null); } var sortedParams = Array.ascSort(resources); if (Util.equalNumber(Array.size(sortedParams), 0)) { return `${canonicalizedResource}\n`; } var subResources = Array.join(sortedParams, '\\n'); return `${canonicalizedResource}\n${subResources}`; } async function buildCanonicalizedHeaders(headers: map[string]any): string { var canonicalizedHeaders : string = ''; var keys = Map.keySet(headers); var sortedHeaders = Array.ascSort(keys); for(var header : sortedHeaders) { if (String.contains(String.toLower(header), 'x-fc-')) { canonicalizedHeaders = `${canonicalizedHeaders}${String.toLower(header)}:${Util.toJSONString(headers[header])}\n`; } } return canonicalizedHeaders; }