Send to zulip

This commit is contained in:
Koper
2023-11-20 21:39:33 +07:00
parent 82f50817f8
commit ba40d28152
3609 changed files with 2311843 additions and 7 deletions

View File

@@ -0,0 +1,89 @@
var util = require('../util');
var AWS = require('../core');
/**
* Prepend prefix defined by API model to endpoint that's already
* constructed. This feature does not apply to operations using
* endpoint discovery and can be disabled.
* @api private
*/
function populateHostPrefix(request) {
var enabled = request.service.config.hostPrefixEnabled;
if (!enabled) return request;
var operationModel = request.service.api.operations[request.operation];
//don't marshal host prefix when operation has endpoint discovery traits
if (hasEndpointDiscover(request)) return request;
if (operationModel.endpoint && operationModel.endpoint.hostPrefix) {
var hostPrefixNotation = operationModel.endpoint.hostPrefix;
var hostPrefix = expandHostPrefix(hostPrefixNotation, request.params, operationModel.input);
prependEndpointPrefix(request.httpRequest.endpoint, hostPrefix);
validateHostname(request.httpRequest.endpoint.hostname);
}
return request;
}
/**
* @api private
*/
function hasEndpointDiscover(request) {
var api = request.service.api;
var operationModel = api.operations[request.operation];
var isEndpointOperation = api.endpointOperation && (api.endpointOperation === util.string.lowerFirst(operationModel.name));
return (operationModel.endpointDiscoveryRequired !== 'NULL' || isEndpointOperation === true);
}
/**
* @api private
*/
function expandHostPrefix(hostPrefixNotation, params, shape) {
util.each(shape.members, function(name, member) {
if (member.hostLabel === true) {
if (typeof params[name] !== 'string' || params[name] === '') {
throw util.error(new Error(), {
message: 'Parameter ' + name + ' should be a non-empty string.',
code: 'InvalidParameter'
});
}
var regex = new RegExp('\\{' + name + '\\}', 'g');
hostPrefixNotation = hostPrefixNotation.replace(regex, params[name]);
}
});
return hostPrefixNotation;
}
/**
* @api private
*/
function prependEndpointPrefix(endpoint, prefix) {
if (endpoint.host) {
endpoint.host = prefix + endpoint.host;
}
if (endpoint.hostname) {
endpoint.hostname = prefix + endpoint.hostname;
}
}
/**
* @api private
*/
function validateHostname(hostname) {
var labels = hostname.split('.');
//Reference: https://tools.ietf.org/html/rfc1123#section-2
var hostPattern = /^[a-zA-Z0-9]{1}$|^[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9]$/;
util.arrayEach(labels, function(label) {
if (!label.length || label.length < 1 || label.length > 63) {
throw util.error(new Error(), {
code: 'ValidationError',
message: 'Hostname label length should be between 1 to 63 characters, inclusive.'
});
}
if (!hostPattern.test(label)) {
throw AWS.util.error(new Error(),
{code: 'ValidationError', message: label + ' is not hostname compatible.'});
}
});
}
module.exports = {
populateHostPrefix: populateHostPrefix
};

View File

@@ -0,0 +1,102 @@
var util = require('../util');
var JsonBuilder = require('../json/builder');
var JsonParser = require('../json/parser');
var populateHostPrefix = require('./helpers').populateHostPrefix;
function buildRequest(req) {
var httpRequest = req.httpRequest;
var api = req.service.api;
var target = api.targetPrefix + '.' + api.operations[req.operation].name;
var version = api.jsonVersion || '1.0';
var input = api.operations[req.operation].input;
var builder = new JsonBuilder();
if (version === 1) version = '1.0';
if (api.awsQueryCompatible) {
if (!httpRequest.params) {
httpRequest.params = {};
}
// because Query protocol does this.
Object.assign(httpRequest.params, req.params);
}
httpRequest.body = builder.build(req.params || {}, input);
httpRequest.headers['Content-Type'] = 'application/x-amz-json-' + version;
httpRequest.headers['X-Amz-Target'] = target;
populateHostPrefix(req);
}
function extractError(resp) {
var error = {};
var httpResponse = resp.httpResponse;
error.code = httpResponse.headers['x-amzn-errortype'] || 'UnknownError';
if (typeof error.code === 'string') {
error.code = error.code.split(':')[0];
}
if (httpResponse.body.length > 0) {
try {
var e = JSON.parse(httpResponse.body.toString());
var code = e.__type || e.code || e.Code;
if (code) {
error.code = code.split('#').pop();
}
if (error.code === 'RequestEntityTooLarge') {
error.message = 'Request body must be less than 1 MB';
} else {
error.message = (e.message || e.Message || null);
}
// The minimized models do not have error shapes, so
// without expanding the model size, it's not possible
// to validate the response shape (members) or
// check if any are sensitive to logging.
// Assign the fields as non-enumerable, allowing specific access only.
for (var key in e || {}) {
if (key === 'code' || key === 'message') {
continue;
}
error['[' + key + ']'] = 'See error.' + key + ' for details.';
Object.defineProperty(error, key, {
value: e[key],
enumerable: false,
writable: true
});
}
} catch (e) {
error.statusCode = httpResponse.statusCode;
error.message = httpResponse.statusMessage;
}
} else {
error.statusCode = httpResponse.statusCode;
error.message = httpResponse.statusCode.toString();
}
resp.error = util.error(new Error(), error);
}
function extractData(resp) {
var body = resp.httpResponse.body.toString() || '{}';
if (resp.request.service.config.convertResponseTypes === false) {
resp.data = JSON.parse(body);
} else {
var operation = resp.request.service.api.operations[resp.request.operation];
var shape = operation.output || {};
var parser = new JsonParser();
resp.data = parser.parse(body, shape);
}
}
/**
* @api private
*/
module.exports = {
buildRequest: buildRequest,
extractError: extractError,
extractData: extractData
};

View File

@@ -0,0 +1,110 @@
var AWS = require('../core');
var util = require('../util');
var QueryParamSerializer = require('../query/query_param_serializer');
var Shape = require('../model/shape');
var populateHostPrefix = require('./helpers').populateHostPrefix;
function buildRequest(req) {
var operation = req.service.api.operations[req.operation];
var httpRequest = req.httpRequest;
httpRequest.headers['Content-Type'] =
'application/x-www-form-urlencoded; charset=utf-8';
httpRequest.params = {
Version: req.service.api.apiVersion,
Action: operation.name
};
// convert the request parameters into a list of query params,
// e.g. Deeply.NestedParam.0.Name=value
var builder = new QueryParamSerializer();
builder.serialize(req.params, operation.input, function(name, value) {
httpRequest.params[name] = value;
});
httpRequest.body = util.queryParamsToString(httpRequest.params);
populateHostPrefix(req);
}
function extractError(resp) {
var data, body = resp.httpResponse.body.toString();
if (body.match('<UnknownOperationException')) {
data = {
Code: 'UnknownOperation',
Message: 'Unknown operation ' + resp.request.operation
};
} else {
try {
data = new AWS.XML.Parser().parse(body);
} catch (e) {
data = {
Code: resp.httpResponse.statusCode,
Message: resp.httpResponse.statusMessage
};
}
}
if (data.requestId && !resp.requestId) resp.requestId = data.requestId;
if (data.Errors) data = data.Errors;
if (data.Error) data = data.Error;
if (data.Code) {
resp.error = util.error(new Error(), {
code: data.Code,
message: data.Message
});
} else {
resp.error = util.error(new Error(), {
code: resp.httpResponse.statusCode,
message: null
});
}
}
function extractData(resp) {
var req = resp.request;
var operation = req.service.api.operations[req.operation];
var shape = operation.output || {};
var origRules = shape;
if (origRules.resultWrapper) {
var tmp = Shape.create({type: 'structure'});
tmp.members[origRules.resultWrapper] = shape;
tmp.memberNames = [origRules.resultWrapper];
util.property(shape, 'name', shape.resultWrapper);
shape = tmp;
}
var parser = new AWS.XML.Parser();
// TODO: Refactor XML Parser to parse RequestId from response.
if (shape && shape.members && !shape.members._XAMZRequestId) {
var requestIdShape = Shape.create(
{ type: 'string' },
{ api: { protocol: 'query' } },
'requestId'
);
shape.members._XAMZRequestId = requestIdShape;
}
var data = parser.parse(resp.httpResponse.body.toString(), shape);
resp.requestId = data._XAMZRequestId || data.requestId;
if (data._XAMZRequestId) delete data._XAMZRequestId;
if (origRules.resultWrapper) {
if (data[origRules.resultWrapper]) {
util.update(data, data[origRules.resultWrapper]);
delete data[origRules.resultWrapper];
}
}
resp.data = data;
}
/**
* @api private
*/
module.exports = {
buildRequest: buildRequest,
extractError: extractError,
extractData: extractData
};

View File

@@ -0,0 +1,148 @@
var util = require('../util');
var populateHostPrefix = require('./helpers').populateHostPrefix;
function populateMethod(req) {
req.httpRequest.method = req.service.api.operations[req.operation].httpMethod;
}
function generateURI(endpointPath, operationPath, input, params) {
var uri = [endpointPath, operationPath].join('/');
uri = uri.replace(/\/+/g, '/');
var queryString = {}, queryStringSet = false;
util.each(input.members, function (name, member) {
var paramValue = params[name];
if (paramValue === null || paramValue === undefined) return;
if (member.location === 'uri') {
var regex = new RegExp('\\{' + member.name + '(\\+)?\\}');
uri = uri.replace(regex, function(_, plus) {
var fn = plus ? util.uriEscapePath : util.uriEscape;
return fn(String(paramValue));
});
} else if (member.location === 'querystring') {
queryStringSet = true;
if (member.type === 'list') {
queryString[member.name] = paramValue.map(function(val) {
return util.uriEscape(member.member.toWireFormat(val).toString());
});
} else if (member.type === 'map') {
util.each(paramValue, function(key, value) {
if (Array.isArray(value)) {
queryString[key] = value.map(function(val) {
return util.uriEscape(String(val));
});
} else {
queryString[key] = util.uriEscape(String(value));
}
});
} else {
queryString[member.name] = util.uriEscape(member.toWireFormat(paramValue).toString());
}
}
});
if (queryStringSet) {
uri += (uri.indexOf('?') >= 0 ? '&' : '?');
var parts = [];
util.arrayEach(Object.keys(queryString).sort(), function(key) {
if (!Array.isArray(queryString[key])) {
queryString[key] = [queryString[key]];
}
for (var i = 0; i < queryString[key].length; i++) {
parts.push(util.uriEscape(String(key)) + '=' + queryString[key][i]);
}
});
uri += parts.join('&');
}
return uri;
}
function populateURI(req) {
var operation = req.service.api.operations[req.operation];
var input = operation.input;
var uri = generateURI(req.httpRequest.endpoint.path, operation.httpPath, input, req.params);
req.httpRequest.path = uri;
}
function populateHeaders(req) {
var operation = req.service.api.operations[req.operation];
util.each(operation.input.members, function (name, member) {
var value = req.params[name];
if (value === null || value === undefined) return;
if (member.location === 'headers' && member.type === 'map') {
util.each(value, function(key, memberValue) {
req.httpRequest.headers[member.name + key] = memberValue;
});
} else if (member.location === 'header') {
value = member.toWireFormat(value).toString();
if (member.isJsonValue) {
value = util.base64.encode(value);
}
req.httpRequest.headers[member.name] = value;
}
});
}
function buildRequest(req) {
populateMethod(req);
populateURI(req);
populateHeaders(req);
populateHostPrefix(req);
}
function extractError() {
}
function extractData(resp) {
var req = resp.request;
var data = {};
var r = resp.httpResponse;
var operation = req.service.api.operations[req.operation];
var output = operation.output;
// normalize headers names to lower-cased keys for matching
var headers = {};
util.each(r.headers, function (k, v) {
headers[k.toLowerCase()] = v;
});
util.each(output.members, function(name, member) {
var header = (member.name || name).toLowerCase();
if (member.location === 'headers' && member.type === 'map') {
data[name] = {};
var location = member.isLocationName ? member.name : '';
var pattern = new RegExp('^' + location + '(.+)', 'i');
util.each(r.headers, function (k, v) {
var result = k.match(pattern);
if (result !== null) {
data[name][result[1]] = v;
}
});
} else if (member.location === 'header') {
if (headers[header] !== undefined) {
var value = member.isJsonValue ?
util.base64.decode(headers[header]) :
headers[header];
data[name] = member.toType(value);
}
} else if (member.location === 'statusCode') {
data[name] = parseInt(r.statusCode, 10);
}
});
resp.data = data;
}
/**
* @api private
*/
module.exports = {
buildRequest: buildRequest,
extractError: extractError,
extractData: extractData,
generateURI: generateURI
};

View File

@@ -0,0 +1,106 @@
var util = require('../util');
var Rest = require('./rest');
var Json = require('./json');
var JsonBuilder = require('../json/builder');
var JsonParser = require('../json/parser');
var METHODS_WITHOUT_BODY = ['GET', 'HEAD', 'DELETE'];
function unsetContentLength(req) {
var payloadMember = util.getRequestPayloadShape(req);
if (
payloadMember === undefined &&
METHODS_WITHOUT_BODY.indexOf(req.httpRequest.method) >= 0
) {
delete req.httpRequest.headers['Content-Length'];
}
}
function populateBody(req) {
var builder = new JsonBuilder();
var input = req.service.api.operations[req.operation].input;
if (input.payload) {
var params = {};
var payloadShape = input.members[input.payload];
params = req.params[input.payload];
if (payloadShape.type === 'structure') {
req.httpRequest.body = builder.build(params || {}, payloadShape);
applyContentTypeHeader(req);
} else if (params !== undefined) {
// non-JSON payload
req.httpRequest.body = params;
if (payloadShape.type === 'binary' || payloadShape.isStreaming) {
applyContentTypeHeader(req, true);
}
}
} else {
req.httpRequest.body = builder.build(req.params, input);
applyContentTypeHeader(req);
}
}
function applyContentTypeHeader(req, isBinary) {
if (!req.httpRequest.headers['Content-Type']) {
var type = isBinary ? 'binary/octet-stream' : 'application/json';
req.httpRequest.headers['Content-Type'] = type;
}
}
function buildRequest(req) {
Rest.buildRequest(req);
// never send body payload on GET/HEAD/DELETE
if (METHODS_WITHOUT_BODY.indexOf(req.httpRequest.method) < 0) {
populateBody(req);
}
}
function extractError(resp) {
Json.extractError(resp);
}
function extractData(resp) {
Rest.extractData(resp);
var req = resp.request;
var operation = req.service.api.operations[req.operation];
var rules = req.service.api.operations[req.operation].output || {};
var parser;
var hasEventOutput = operation.hasEventOutput;
if (rules.payload) {
var payloadMember = rules.members[rules.payload];
var body = resp.httpResponse.body;
if (payloadMember.isEventStream) {
parser = new JsonParser();
resp.data[payload] = util.createEventStream(
AWS.HttpClient.streamsApiVersion === 2 ? resp.httpResponse.stream : body,
parser,
payloadMember
);
} else if (payloadMember.type === 'structure' || payloadMember.type === 'list') {
var parser = new JsonParser();
resp.data[rules.payload] = parser.parse(body, payloadMember);
} else if (payloadMember.type === 'binary' || payloadMember.isStreaming) {
resp.data[rules.payload] = body;
} else {
resp.data[rules.payload] = payloadMember.toType(body);
}
} else {
var data = resp.data;
Json.extractData(resp);
resp.data = util.merge(data, resp.data);
}
}
/**
* @api private
*/
module.exports = {
buildRequest: buildRequest,
extractError: extractError,
extractData: extractData,
unsetContentLength: unsetContentLength
};

View File

@@ -0,0 +1,108 @@
var AWS = require('../core');
var util = require('../util');
var Rest = require('./rest');
function populateBody(req) {
var input = req.service.api.operations[req.operation].input;
var builder = new AWS.XML.Builder();
var params = req.params;
var payload = input.payload;
if (payload) {
var payloadMember = input.members[payload];
params = params[payload];
if (params === undefined) return;
if (payloadMember.type === 'structure') {
var rootElement = payloadMember.name;
req.httpRequest.body = builder.toXML(params, payloadMember, rootElement, true);
} else { // non-xml payload
req.httpRequest.body = params;
}
} else {
req.httpRequest.body = builder.toXML(params, input, input.name ||
input.shape || util.string.upperFirst(req.operation) + 'Request');
}
}
function buildRequest(req) {
Rest.buildRequest(req);
// never send body payload on GET/HEAD
if (['GET', 'HEAD'].indexOf(req.httpRequest.method) < 0) {
populateBody(req);
}
}
function extractError(resp) {
Rest.extractError(resp);
var data;
try {
data = new AWS.XML.Parser().parse(resp.httpResponse.body.toString());
} catch (e) {
data = {
Code: resp.httpResponse.statusCode,
Message: resp.httpResponse.statusMessage
};
}
if (data.Errors) data = data.Errors;
if (data.Error) data = data.Error;
if (data.Code) {
resp.error = util.error(new Error(), {
code: data.Code,
message: data.Message
});
} else {
resp.error = util.error(new Error(), {
code: resp.httpResponse.statusCode,
message: null
});
}
}
function extractData(resp) {
Rest.extractData(resp);
var parser;
var req = resp.request;
var body = resp.httpResponse.body;
var operation = req.service.api.operations[req.operation];
var output = operation.output;
var hasEventOutput = operation.hasEventOutput;
var payload = output.payload;
if (payload) {
var payloadMember = output.members[payload];
if (payloadMember.isEventStream) {
parser = new AWS.XML.Parser();
resp.data[payload] = util.createEventStream(
AWS.HttpClient.streamsApiVersion === 2 ? resp.httpResponse.stream : resp.httpResponse.body,
parser,
payloadMember
);
} else if (payloadMember.type === 'structure') {
parser = new AWS.XML.Parser();
resp.data[payload] = parser.parse(body.toString(), payloadMember);
} else if (payloadMember.type === 'binary' || payloadMember.isStreaming) {
resp.data[payload] = body;
} else {
resp.data[payload] = payloadMember.toType(body);
}
} else if (body.length > 0) {
parser = new AWS.XML.Parser();
var data = parser.parse(body.toString(), output);
util.update(resp.data, data);
}
}
/**
* @api private
*/
module.exports = {
buildRequest: buildRequest,
extractError: extractError,
extractData: extractData
};