alibabacloud-gateway-pop/main.tea (286 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;
type @endpointSuffix = string
type @signatureTypePrefix = string
type @signPrefix = string
type @sha256 = string
type @sm3 = string
init() {
super();
// CLOUD4-
@signatureTypePrefix = 'ACS4-';
// cloud_v4
@signPrefix = 'aliyun_v4';
@endpointSuffix = 'aliyuncs.com';
@sha256 = `${@signatureTypePrefix}HMAC-SHA256`;
@sm3 = `${@signatureTypePrefix}HMAC-SM3`;
}
async function modifyConfiguration(context: SPI.InterceptorContext, attributeMap: SPI.AttributeMap): void {
var request = context.request;
var config = context.configuration;
var attributes = attributeMap.key;
if (!Util.isUnset(attributes)) {
@signatureTypePrefix = attributes.signatureTypePrefix;
@signPrefix = attributes.signPrefix;
@endpointSuffix = attributes.endpointSuffix;
@sha256 = `${@signatureTypePrefix}HMAC-SHA256`;
@sm3 = `${@signatureTypePrefix}HMAC-SM3`;
}
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 request = context.request;
var config = context.configuration;
var date = OpenApiUtil.getTimestamp();
request.headers = {
host = config.endpoint,
x-acs-version = request.version,
x-acs-action = request.action,
user-agent = request.userAgent,
x-acs-date = date,
x-acs-signature-nonce = Util.getNonce(),
accept = 'application/json',
...request.headers
};
var signatureAlgorithm : string = Util.defaultString(request.signatureAlgorithm, @sha256);
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';
}
}
}
if (Util.equalString(signatureAlgorithm, @sm3)) {
request.headers.x-acs-content-sm3 = hashedRequestPayload;
} else {
request.headers.x-acs-content-sha256 = hashedRequestPayload;
}
if (!Util.equalString(request.authType, 'Anonymous')) {
var credential : Credential = request.credential;
if (Util.isUnset(credential)) {
throw {
code = 'ParameterMissing',
message = '\'config.credential\' can not be unset'
};
}
var credentialModel = credential.getCredential();
if (!Util.empty(credentialModel.providerName)) {
request.headers.x-acs-credentials-provider = credentialModel.providerName;
}
var authType = credentialModel.type;
if (Util.equalString(authType, 'bearer')) {
var bearerToken = credential.getBearerToken();
request.headers.x-acs-bearer-token = bearerToken;
request.headers.x-acs-signature-type = 'BEARERTOKEN';
request.headers.Authorization = `Bearer ${bearerToken}`;
} else if (Util.equalString(authType, 'id_token')) {
var idToken = credentialModel.securityToken;
request.headers.x-acs-zero-trust-idtoken = idToken;
} else {
var accessKeyId = credentialModel.accessKeyId;
var accessKeySecret = credentialModel.accessKeySecret;
var securityToken = credentialModel.securityToken;
if (!Util.empty(securityToken)) {
request.headers.x-acs-accesskey-id = accessKeyId;
request.headers.x-acs-security-token = securityToken;
}
var dateNew = String.subString(date, 0, 10);
dateNew = String.replace(dateNew, '-', '', null);
var region = getRegion(request.productId, config.endpoint, config.regionId);
var signingkey = getSigningkey(signatureAlgorithm, accessKeySecret, request.productId, region, dateNew);
request.headers.Authorization = getAuthorization(request.pathname, request.method, request.query, request.headers, signatureAlgorithm, hashedRequestPayload, accessKeyId, signingkey, request.productId, region, dateNew);
}
}
}
async function modifyResponse(context: SPI.InterceptorContext, attributeMap: SPI.AttributeMap): void {
var request = context.request;
var response = context.response;
if (Util.is4xx(response.statusCode) || Util.is5xx(response.statusCode)) {
var _res = Util.readAsJSON(response.body);
var err = Util.assertAsMap(_res);
var requestId = defaultAny(err.RequestId, err.requestId);
if (!Util.isUnset(response.headers.x-acs-request-id)) {
requestId = response.headers.x-acs-request-id;
}
err.statusCode = response.statusCode;
throw {
code = `${defaultAny(err.Code, err.code)}`,
message = `code: ${response.statusCode}, ${defaultAny(err.Message, err.message)} request id: ${requestId}`,
data = err,
description = `${defaultAny(err.Description, err.description)}`,
accessDeniedDetail = defaultAny(err.AccessDeniedDetail, err.accessDeniedDetail),
};
}
if (Util.equalNumber(response.statusCode, 204)) {
Util.readAsString(response.body);
} else 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 getAuthorization(pathname: string, method: string, query: map[string]string, headers: map[string]string, signatureAlgorithm: string, payload: string, ak: string, signingkey: bytes, product: string, region: string, date: string): string {
var signature = getSignature(pathname, method, query, headers, signatureAlgorithm, payload, signingkey);
var signedHeaders = getSignedHeaders(headers);
var signedHeadersStr = Array.join(signedHeaders, ';');
return `${signatureAlgorithm} Credential=${ak}/${date}/${region}/${product}/${@signPrefix}_request,SignedHeaders=${signedHeadersStr},Signature=${signature}`;
}
async function getSignature(pathname: string, method: string, query: map[string]string, headers: map[string]string, signatureAlgorithm: string, payload: string, signingkey: bytes): string {
var canonicalURI : string = '/';
if (!Util.empty(pathname)) {
canonicalURI = pathname;
}
var stringToSign : string = '';
var canonicalizedResource = buildCanonicalizedResource(query);
var canonicalizedHeaders = buildCanonicalizedHeaders(headers);
var signedHeaders = getSignedHeaders(headers);
var signedHeadersStr = Array.join(signedHeaders, ';');
stringToSign = `${method}\n${canonicalURI}\n${canonicalizedResource}\n${canonicalizedHeaders}\n${signedHeadersStr}\n${payload}`;
var hex = EncodeUtil.hexEncode(EncodeUtil.hash(Util.toBytes(stringToSign), signatureAlgorithm));
stringToSign = `${signatureAlgorithm}\n${hex}`;
var signature = Util.toBytes('');
if (Util.equalString(signatureAlgorithm, @sha256)) {
signature = SignatureUtil.HmacSHA256SignByBytes(stringToSign, signingkey);
} else if (Util.equalString(signatureAlgorithm, @sm3)) {
signature = SignatureUtil.HmacSM3SignByBytes(stringToSign, signingkey);
}
return EncodeUtil.hexEncode(signature);
}
async function getSigningkey(signatureAlgorithm: string, secret: string, product: string, region: string, date: string): bytes {
var sc1 = `${@signPrefix}${secret}`;
var sc2 = Util.toBytes('');
if (Util.equalString(signatureAlgorithm, @sha256)) {
sc2 = SignatureUtil.HmacSHA256Sign(date, sc1);
} else if (Util.equalString(signatureAlgorithm, @sm3)) {
sc2 = SignatureUtil.HmacSM3Sign(date, sc1);
}
var sc3 = Util.toBytes('');
if (Util.equalString(signatureAlgorithm, @sha256)) {
sc3 = SignatureUtil.HmacSHA256SignByBytes(region, sc2);
} else if (Util.equalString(signatureAlgorithm, @sm3)) {
sc3 = SignatureUtil.HmacSM3SignByBytes(region, sc2);
}
var sc4 = Util.toBytes('');
if (Util.equalString(signatureAlgorithm, @sha256)) {
sc4 = SignatureUtil.HmacSHA256SignByBytes(product, sc3);
} else if (Util.equalString(signatureAlgorithm, @sm3)) {
sc4 = SignatureUtil.HmacSM3SignByBytes(product, sc3);
}
var hmac = Util.toBytes('');
if (Util.equalString(signatureAlgorithm, @sha256)) {
hmac = SignatureUtil.HmacSHA256SignByBytes(`${@signPrefix}_request`, sc4);
} else if (Util.equalString(signatureAlgorithm, @sm3)) {
hmac = SignatureUtil.HmacSM3SignByBytes(`${@signPrefix}_request`, sc4);
}
return hmac;
}
function getRegion(product: string, endpoint: string, regionId: string): string {
if (!Util.empty(regionId)) {
return regionId;
}
var region = 'center';
if (Util.empty(product) || Util.empty(endpoint)) {
return region;
}
var strs : [string] = String.split(endpoint, ':', null);
var withoutPort : string = strs[0];
var preRegion: string = String.replace(withoutPort, `.${@endpointSuffix}`, '', null);
var nodes = String.split(preRegion, '.', null);
if (Util.equalNumber(Array.size(nodes), 2)) {
region = nodes[1];
}
return region;
}
async function buildCanonicalizedResource(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 buildCanonicalizedHeaders(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);
}