Files
awesome-reviewers/_reviewers/aws-sdk-js-validate-configurations-with-clarity.json
2025-07-03 10:48:16 +03:00

68 lines
41 KiB
JSON

[
{
"discussion_id": "227568468",
"pr_number": 2253,
"pr_file": "lib/discover_endpoint.js",
"created_at": "2018-10-23T21:18:49+00:00",
"commented_code": "var AWS = require('./core');\nvar util = require('./util');\nvar ENDPOINT_OPERATION_MAX_RETRIES = 60;\nvar endpointDiscoveryEnabledEnv = 'AWS_ENABLE_ENDPOINT_DISCOVERY';\n\n/**\n * Generate key to index the endpoints in the cache\n * @return [map<String,String>] object with keys to index endpoints.\n * @api private\n */\nfunction getCacheKey(request) {\n var service = request.service;\n var api = service.api || {};\n var operations = api.operations;\n var identifiers = {};\n if (operations[request.operation] && operations[request.operation].name) {\n identifiers.operation = operations[request.operation].name;\n }\n if (service.config.region) {\n identifiers.region = service.config.region;\n }\n if (api.serviceId) {\n identifiers.serviceId = api.serviceId\n }\n if (service.config.credentials.accessKeyId) {\n identifiers.accessKeyId = service.config.credentials.accessKeyId\n }\n return identifiers;\n}\n\n/**\n * @api private\n */\nfunction marshallCustomeIdentifiersHelper(result, params, shape) {\n if (!shape || params === undefined || params === null) return;\n if (shape.type === 'structure' && shape.required && shape.required.length > 0) {\n util.arrayEach(shape.required, function(name) {\n var memberShape = shape.members[name];\n if (memberShape.endpointDiscoveryId === true) {\n var locationName = memberShape.isLocationName ? memberShape.name : name;\n result[locationName] = String(params[name]);\n } else {\n marshallCustomeIdentifiersHelper(result, params[name], memberShape);\n }\n });\n }\n}\n\n/**\n * Get customized cache key according to the 'endpointDiscoveryId' trait.\n * @param [object] request object\n * @param [object] input shape of the given operation's api\n */\nfunction marshallCustomeIdentifiers(request, shape) {\n var identifiers = {};\n marshallCustomeIdentifiersHelper(identifiers, request.params, shape);\n return identifiers;\n}\n\n/**\n * Call endpoint discovery operation when it's optional.\n * When endpoint is available in cache then use the cached endpoints. If endpoints\n * are unavailable then use regional endpoints and call endpoint discovery operation\n * asynchronously. This is turned off by default.\n * @param [object] request object\n * @api private\n */\nfunction optionalDisverEndpoint(request) {\n var service = request.service;\n var api = service.api;\n var operationModel = api.operations ? api.operations[request.operation] : undefined;\n var inputShape = operationModel ? operationModel.input : undefined;\n\n var identifiers = marshallCustomeIdentifiers(request, inputShape);\n var cacheKey = getCacheKey(request);\n cacheKey = util.update(cacheKey, identifiers);\n var endpoints = AWS.endpointCache.get(cacheKey);\n if (endpoints && endpoints.length > 0) {\n //found endpoint record from cache\n request.httpRequest.updateEndpoint(endpoints[0].Address);\n } else if (endpoints && endpoints.length === 0) {\n //endpoint operation is being made but response not yet received\n return;\n } else {\n //endpoint record not in cache. make discovery operation\n var endpointRequest = service.makeRequest(api.endpointOperation, {\n Operation: operationModel.name,\n Identifiers: identifiers,\n });\n addApiVersionHeader(endpointRequest);\n endpointRequest.removeListener('validate', AWS.EventListeners.Core.VALIDATE_PARAMETERS);\n endpointRequest.removeListener('retry', AWS.EventListeners.Core.RETRY_CHECK);\n var toHead = true;\n //if endpoint operation failed, keep retrying every minute.\n endpointRequest.on('retry', function(resp) {\n var err = resp.error;\n err.retryable = true;\n err.retryDelay = 60000;\n resp.maxRetries = ENDPOINT_OPERATION_MAX_RETRIES;\n }, toHead);\n //put in a placeholder for endpoints already requested, prevent\n //too much in-flight calls\n AWS.endpointCache.put(cacheKey, []);\n endpointRequest.send(function(err, data) {\n if (data && data.Endpoints) {\n AWS.endpointCache.put(cacheKey, data.Endpoints);\n } else if (err) {\n AWS.endpointCache.remove(cacheKey);\n }\n });\n }\n}\n\n/**\n * Call endpoint discovery operation when it's required.\n * When endpoint is available in cache then use cached ones. If endpoins are\n * unavailable then SDK should call endpoint operation end use returned new\n * endpoint for the api call. SDK will automatically attempt to do endpoint\n * discovery regardless the configuration.\n * @param [object] request object\n * @api private\n */\nfunction requiredDiscoverEndpoint(request, done) {\n var service = request.service;\n var api = service.api;\n var operationModel = api.operations ? api.operations[request.operation] : undefined;\n var inputShape = operationModel ? operationModel.input : undefined;\n\n var identifiers = marshallCustomeIdentifiers(request, inputShape);\n var cacheKey = getCacheKey(request);\n cacheKey = util.update(cacheKey, identifiers);\n var endpoints = AWS.endpointCache.get(cacheKey);\n if (endpoints === undefined || endpoints.length === 0) {\n var endpointRequest = service.makeRequest(api.endpointOperation, {\n Operation: operationModel.name,\n Identifiers: identifiers,\n });\n endpointRequest.removeListener('validate', AWS.EventListeners.Core.VALIDATE_PARAMETERS);\n addApiVersionHeader(endpointRequest);\n endpointRequest.send(function(err, data) {\n if (err) {\n request.response.error = util.error(err, {\n code: 'EndpointDiscoveryException',\n message: 'Request cannot be fulfilled without specifying an endpoint',\n retryable: false\n });\n } else if (data) {\n AWS.endpointCache.put(cacheKey, data.Endpoints);\n request.httpRequest.updateEndpoint(data.Endpoints[0].Address);\n }\n done();\n });\n } else {\n request.httpRequest.updateEndpoint(endpoints[0].Address);\n done();\n }\n}\n\n/**\n * add api version header to endpoint operation\n * @api private\n */\nfunction addApiVersionHeader(endpointRequest) {\n var api = endpointRequest.service.api;\n var apiVersion = api.apiVersion;\n if (apiVersion && !endpointRequest.httpRequest.headers['x-amz-api-version']) {\n endpointRequest.httpRequest.headers['x-amz-api-version'] = apiVersion;\n }\n}\n\n/**\n * If api call gets invalid endoint exception, SDK should attempt to remove the invalid\n * endpoint from cache.\n * @api private\n */\nfunction invalidateCachedEndpoints(response) {\n var error = response.error;\n var httpResponse = response.httpResponse;\n if (error &&\n (error.code === 'InvalidEndpointException' || httpResponse.statusCode === 421)\n ) {\n var request = response.request;\n var operations = request.service.api.operations || {};\n var inputShape = operations[request.operation] ? operations[request.operation].input : undefined;\n var identifiers = marshallCustomeIdentifiers(request, inputShape);\n var cacheKey = getCacheKey(request);\n cacheKey = util.update(cacheKey, identifiers);\n AWS.endpointCache.remove(cacheKey);\n }\n}\n\n/**\n * If endpoint is explicitly configured, SDK should not do endpoint discovery in anytime.\n * @param [object] clien Service client object.\n * @api private\n */\nfunction hasCustomEndpoint(client) {\n //if set endpoint is set for specific client, enable endpoint discovery will raise an error.\n if (client._originalConfig && client._originalConfig.endpoint && client._originalConfig.endpointDiscoveryEnabled === true) {\n throw util.error(new Error(), {\n code: 'ConfigurationException',\n message: 'If custome endpoint is supplied, endpointDiscoverEnabled should be turned off.'\n });\n };\n var svcConfig = AWS.config[client.serviceIdentifier] || {};\n return AWS.config.endpoint || svcConfig.endpoint || (client._originalConfig && client._originalConfig.endpoint);\n}\n\n/**\n * @api private\n */\nfunction isFalsey(value) {\n return ['false', '0'].indexOf(value) >= 0;\n}\n\n/**\n * If endpoint discovery should perform for this request when endpoint discovery is optional.\n * SDK performs config resolution in order like below:\n * 1. If turned on client configuration(default to off) then turn on endpoint discovery.\n * 2. If turned on in env AWS_ENABLE_ENDPOINT_DISCOVERY then turn on endpoint discovery.\n * 3. If turned on in shared ini config file with key 'endpoint_discovery_enabled', then\n * turn on endpoint discovery.\n * @param [object] request request object.\n * @api private\n */\nfunction isEndpointDiscoveryApplicable(request) {\n var service = request.service || {};\n if (service.config.endpointDiscoveryEnabled === true) return true;\n if (Object.prototype.hasOwnProperty.call(process.env, endpointDiscoveryEnabledEnv)) {\n if (process.env[endpointDiscoveryEnabledEnv] === undefined) {",
"repo_full_name": "aws/aws-sdk-js",
"discussion_comments": [
{
"comment_id": "227568468",
"repo_full_name": "aws/aws-sdk-js",
"pr_number": 2253,
"pr_file": "lib/discover_endpoint.js",
"discussion_id": "227568468",
"commented_code": "@@ -0,0 +1,305 @@\n+var AWS = require('./core');\n+var util = require('./util');\n+var ENDPOINT_OPERATION_MAX_RETRIES = 60;\n+var endpointDiscoveryEnabledEnv = 'AWS_ENABLE_ENDPOINT_DISCOVERY';\n+\n+/**\n+ * Generate key to index the endpoints in the cache\n+ * @return [map<String,String>] object with keys to index endpoints.\n+ * @api private\n+ */\n+function getCacheKey(request) {\n+ var service = request.service;\n+ var api = service.api || {};\n+ var operations = api.operations;\n+ var identifiers = {};\n+ if (operations[request.operation] && operations[request.operation].name) {\n+ identifiers.operation = operations[request.operation].name;\n+ }\n+ if (service.config.region) {\n+ identifiers.region = service.config.region;\n+ }\n+ if (api.serviceId) {\n+ identifiers.serviceId = api.serviceId\n+ }\n+ if (service.config.credentials.accessKeyId) {\n+ identifiers.accessKeyId = service.config.credentials.accessKeyId\n+ }\n+ return identifiers;\n+}\n+\n+/**\n+ * @api private\n+ */\n+function marshallCustomeIdentifiersHelper(result, params, shape) {\n+ if (!shape || params === undefined || params === null) return;\n+ if (shape.type === 'structure' && shape.required && shape.required.length > 0) {\n+ util.arrayEach(shape.required, function(name) {\n+ var memberShape = shape.members[name];\n+ if (memberShape.endpointDiscoveryId === true) {\n+ var locationName = memberShape.isLocationName ? memberShape.name : name;\n+ result[locationName] = String(params[name]);\n+ } else {\n+ marshallCustomeIdentifiersHelper(result, params[name], memberShape);\n+ }\n+ });\n+ }\n+}\n+\n+/**\n+ * Get customized cache key according to the 'endpointDiscoveryId' trait.\n+ * @param [object] request object\n+ * @param [object] input shape of the given operation's api\n+ */\n+function marshallCustomeIdentifiers(request, shape) {\n+ var identifiers = {};\n+ marshallCustomeIdentifiersHelper(identifiers, request.params, shape);\n+ return identifiers;\n+}\n+\n+/**\n+ * Call endpoint discovery operation when it's optional.\n+ * When endpoint is available in cache then use the cached endpoints. If endpoints\n+ * are unavailable then use regional endpoints and call endpoint discovery operation\n+ * asynchronously. This is turned off by default.\n+ * @param [object] request object\n+ * @api private\n+ */\n+function optionalDisverEndpoint(request) {\n+ var service = request.service;\n+ var api = service.api;\n+ var operationModel = api.operations ? api.operations[request.operation] : undefined;\n+ var inputShape = operationModel ? operationModel.input : undefined;\n+\n+ var identifiers = marshallCustomeIdentifiers(request, inputShape);\n+ var cacheKey = getCacheKey(request);\n+ cacheKey = util.update(cacheKey, identifiers);\n+ var endpoints = AWS.endpointCache.get(cacheKey);\n+ if (endpoints && endpoints.length > 0) {\n+ //found endpoint record from cache\n+ request.httpRequest.updateEndpoint(endpoints[0].Address);\n+ } else if (endpoints && endpoints.length === 0) {\n+ //endpoint operation is being made but response not yet received\n+ return;\n+ } else {\n+ //endpoint record not in cache. make discovery operation\n+ var endpointRequest = service.makeRequest(api.endpointOperation, {\n+ Operation: operationModel.name,\n+ Identifiers: identifiers,\n+ });\n+ addApiVersionHeader(endpointRequest);\n+ endpointRequest.removeListener('validate', AWS.EventListeners.Core.VALIDATE_PARAMETERS);\n+ endpointRequest.removeListener('retry', AWS.EventListeners.Core.RETRY_CHECK);\n+ var toHead = true;\n+ //if endpoint operation failed, keep retrying every minute.\n+ endpointRequest.on('retry', function(resp) {\n+ var err = resp.error;\n+ err.retryable = true;\n+ err.retryDelay = 60000;\n+ resp.maxRetries = ENDPOINT_OPERATION_MAX_RETRIES;\n+ }, toHead);\n+ //put in a placeholder for endpoints already requested, prevent\n+ //too much in-flight calls\n+ AWS.endpointCache.put(cacheKey, []);\n+ endpointRequest.send(function(err, data) {\n+ if (data && data.Endpoints) {\n+ AWS.endpointCache.put(cacheKey, data.Endpoints);\n+ } else if (err) {\n+ AWS.endpointCache.remove(cacheKey);\n+ }\n+ });\n+ }\n+}\n+\n+/**\n+ * Call endpoint discovery operation when it's required.\n+ * When endpoint is available in cache then use cached ones. If endpoins are\n+ * unavailable then SDK should call endpoint operation end use returned new\n+ * endpoint for the api call. SDK will automatically attempt to do endpoint\n+ * discovery regardless the configuration.\n+ * @param [object] request object\n+ * @api private\n+ */\n+function requiredDiscoverEndpoint(request, done) {\n+ var service = request.service;\n+ var api = service.api;\n+ var operationModel = api.operations ? api.operations[request.operation] : undefined;\n+ var inputShape = operationModel ? operationModel.input : undefined;\n+\n+ var identifiers = marshallCustomeIdentifiers(request, inputShape);\n+ var cacheKey = getCacheKey(request);\n+ cacheKey = util.update(cacheKey, identifiers);\n+ var endpoints = AWS.endpointCache.get(cacheKey);\n+ if (endpoints === undefined || endpoints.length === 0) {\n+ var endpointRequest = service.makeRequest(api.endpointOperation, {\n+ Operation: operationModel.name,\n+ Identifiers: identifiers,\n+ });\n+ endpointRequest.removeListener('validate', AWS.EventListeners.Core.VALIDATE_PARAMETERS);\n+ addApiVersionHeader(endpointRequest);\n+ endpointRequest.send(function(err, data) {\n+ if (err) {\n+ request.response.error = util.error(err, {\n+ code: 'EndpointDiscoveryException',\n+ message: 'Request cannot be fulfilled without specifying an endpoint',\n+ retryable: false\n+ });\n+ } else if (data) {\n+ AWS.endpointCache.put(cacheKey, data.Endpoints);\n+ request.httpRequest.updateEndpoint(data.Endpoints[0].Address);\n+ }\n+ done();\n+ });\n+ } else {\n+ request.httpRequest.updateEndpoint(endpoints[0].Address);\n+ done();\n+ }\n+}\n+\n+/**\n+ * add api version header to endpoint operation\n+ * @api private\n+ */\n+function addApiVersionHeader(endpointRequest) {\n+ var api = endpointRequest.service.api;\n+ var apiVersion = api.apiVersion;\n+ if (apiVersion && !endpointRequest.httpRequest.headers['x-amz-api-version']) {\n+ endpointRequest.httpRequest.headers['x-amz-api-version'] = apiVersion;\n+ }\n+}\n+\n+/**\n+ * If api call gets invalid endoint exception, SDK should attempt to remove the invalid\n+ * endpoint from cache.\n+ * @api private\n+ */\n+function invalidateCachedEndpoints(response) {\n+ var error = response.error;\n+ var httpResponse = response.httpResponse;\n+ if (error &&\n+ (error.code === 'InvalidEndpointException' || httpResponse.statusCode === 421)\n+ ) {\n+ var request = response.request;\n+ var operations = request.service.api.operations || {};\n+ var inputShape = operations[request.operation] ? operations[request.operation].input : undefined;\n+ var identifiers = marshallCustomeIdentifiers(request, inputShape);\n+ var cacheKey = getCacheKey(request);\n+ cacheKey = util.update(cacheKey, identifiers);\n+ AWS.endpointCache.remove(cacheKey);\n+ }\n+}\n+\n+/**\n+ * If endpoint is explicitly configured, SDK should not do endpoint discovery in anytime.\n+ * @param [object] clien Service client object.\n+ * @api private\n+ */\n+function hasCustomEndpoint(client) {\n+ //if set endpoint is set for specific client, enable endpoint discovery will raise an error.\n+ if (client._originalConfig && client._originalConfig.endpoint && client._originalConfig.endpointDiscoveryEnabled === true) {\n+ throw util.error(new Error(), {\n+ code: 'ConfigurationException',\n+ message: 'If custome endpoint is supplied, endpointDiscoverEnabled should be turned off.'\n+ });\n+ };\n+ var svcConfig = AWS.config[client.serviceIdentifier] || {};\n+ return AWS.config.endpoint || svcConfig.endpoint || (client._originalConfig && client._originalConfig.endpoint);\n+}\n+\n+/**\n+ * @api private\n+ */\n+function isFalsey(value) {\n+ return ['false', '0'].indexOf(value) >= 0;\n+}\n+\n+/**\n+ * If endpoint discovery should perform for this request when endpoint discovery is optional.\n+ * SDK performs config resolution in order like below:\n+ * 1. If turned on client configuration(default to off) then turn on endpoint discovery.\n+ * 2. If turned on in env AWS_ENABLE_ENDPOINT_DISCOVERY then turn on endpoint discovery.\n+ * 3. If turned on in shared ini config file with key 'endpoint_discovery_enabled', then\n+ * turn on endpoint discovery.\n+ * @param [object] request request object.\n+ * @api private\n+ */\n+function isEndpointDiscoveryApplicable(request) {\n+ var service = request.service || {};\n+ if (service.config.endpointDiscoveryEnabled === true) return true;\n+ if (Object.prototype.hasOwnProperty.call(process.env, endpointDiscoveryEnabledEnv)) {\n+ if (process.env[endpointDiscoveryEnabledEnv] === undefined) {",
"comment_created_at": "2018-10-23T21:18:49+00:00",
"comment_author": "chrisradek",
"comment_body": "Is it possible to have an environment variable that is not a string in node.js?\r\nI haven't tried in Windows, but on MacOS, that doesn't seem possible.\r\n```bash\r\nFOO=bar node -e \"console.log(process.env)\"\r\n# FOO: 'bar'\r\n```\r\n```bash\r\nFOO= node -e \"console.log(process.env)\"\r\n# FOO: ''\r\n```\r\n\r\n```bash\r\nnode -e \"process.env['FOO'] = void 0; console.log(process.env)\"\r\n# FOO: 'undefined'\r\n```\r\n\r\nEven trying to set it to undefined within the process still results in the variable being a string. If you want to throw an error when this variable is set to nothing, you might want to instead check if it is an empty string.",
"pr_file_module": null
}
]
},
{
"discussion_id": "227596555",
"pr_number": 2253,
"pr_file": "lib/discover_endpoint.js",
"created_at": "2018-10-23T23:12:33+00:00",
"commented_code": "var AWS = require('./core');\nvar util = require('./util');\nvar ENDPOINT_OPERATION_MAX_RETRIES = 60;\nvar endpointDiscoveryEnabledEnv = 'AWS_ENABLE_ENDPOINT_DISCOVERY';\n\n/**\n * Generate key to index the endpoints in the cache\n * @return [map<String,String>] object with keys to index endpoints.\n * @api private\n */\nfunction getCacheKey(request) {\n var service = request.service;\n var api = service.api || {};\n var operations = api.operations;\n var identifiers = {};\n if (operations[request.operation] && operations[request.operation].name) {\n identifiers.operation = operations[request.operation].name;\n }\n if (service.config.region) {\n identifiers.region = service.config.region;\n }\n if (api.serviceId) {\n identifiers.serviceId = api.serviceId\n }\n if (service.config.credentials.accessKeyId) {\n identifiers.accessKeyId = service.config.credentials.accessKeyId\n }\n return identifiers;\n}\n\n/**\n * @api private\n */\nfunction marshallCustomeIdentifiersHelper(result, params, shape) {\n if (!shape || params === undefined || params === null) return;\n if (shape.type === 'structure' && shape.required && shape.required.length > 0) {\n util.arrayEach(shape.required, function(name) {\n var memberShape = shape.members[name];\n if (memberShape.endpointDiscoveryId === true) {\n var locationName = memberShape.isLocationName ? memberShape.name : name;\n result[locationName] = String(params[name]);\n } else {\n marshallCustomeIdentifiersHelper(result, params[name], memberShape);\n }\n });\n }\n}\n\n/**\n * Get customized cache key according to the 'endpointDiscoveryId' trait.\n * @param [object] request object\n * @param [object] input shape of the given operation's api\n */\nfunction marshallCustomeIdentifiers(request, shape) {\n var identifiers = {};\n marshallCustomeIdentifiersHelper(identifiers, request.params, shape);\n return identifiers;\n}\n\n/**\n * Call endpoint discovery operation when it's optional.\n * When endpoint is available in cache then use the cached endpoints. If endpoints\n * are unavailable then use regional endpoints and call endpoint discovery operation\n * asynchronously. This is turned off by default.\n * @param [object] request object\n * @api private\n */\nfunction optionalDisverEndpoint(request) {\n var service = request.service;\n var api = service.api;\n var operationModel = api.operations ? api.operations[request.operation] : undefined;\n var inputShape = operationModel ? operationModel.input : undefined;\n\n var identifiers = marshallCustomeIdentifiers(request, inputShape);\n var cacheKey = getCacheKey(request);\n cacheKey = util.update(cacheKey, identifiers);\n var endpoints = AWS.endpointCache.get(cacheKey);\n if (endpoints && endpoints.length > 0) {\n //found endpoint record from cache\n request.httpRequest.updateEndpoint(endpoints[0].Address);\n } else if (endpoints && endpoints.length === 0) {\n //endpoint operation is being made but response not yet received\n return;\n } else {\n //endpoint record not in cache. make discovery operation\n var endpointRequest = service.makeRequest(api.endpointOperation, {\n Operation: operationModel.name,\n Identifiers: identifiers,\n });\n addApiVersionHeader(endpointRequest);\n endpointRequest.removeListener('validate', AWS.EventListeners.Core.VALIDATE_PARAMETERS);\n endpointRequest.removeListener('retry', AWS.EventListeners.Core.RETRY_CHECK);\n var toHead = true;\n //if endpoint operation failed, keep retrying every minute.\n endpointRequest.on('retry', function(resp) {\n var err = resp.error;\n err.retryable = true;\n err.retryDelay = 60000;\n resp.maxRetries = ENDPOINT_OPERATION_MAX_RETRIES;\n }, toHead);\n //put in a placeholder for endpoints already requested, prevent\n //too much in-flight calls\n AWS.endpointCache.put(cacheKey, []);\n endpointRequest.send(function(err, data) {\n if (data && data.Endpoints) {\n AWS.endpointCache.put(cacheKey, data.Endpoints);\n } else if (err) {\n AWS.endpointCache.remove(cacheKey);\n }\n });\n }\n}\n\n/**\n * Call endpoint discovery operation when it's required.\n * When endpoint is available in cache then use cached ones. If endpoins are\n * unavailable then SDK should call endpoint operation end use returned new\n * endpoint for the api call. SDK will automatically attempt to do endpoint\n * discovery regardless the configuration.\n * @param [object] request object\n * @api private\n */\nfunction requiredDiscoverEndpoint(request, done) {\n var service = request.service;\n var api = service.api;\n var operationModel = api.operations ? api.operations[request.operation] : undefined;\n var inputShape = operationModel ? operationModel.input : undefined;\n\n var identifiers = marshallCustomeIdentifiers(request, inputShape);\n var cacheKey = getCacheKey(request);\n cacheKey = util.update(cacheKey, identifiers);\n var endpoints = AWS.endpointCache.get(cacheKey);\n if (endpoints === undefined || endpoints.length === 0) {\n var endpointRequest = service.makeRequest(api.endpointOperation, {\n Operation: operationModel.name,\n Identifiers: identifiers,\n });\n endpointRequest.removeListener('validate', AWS.EventListeners.Core.VALIDATE_PARAMETERS);\n addApiVersionHeader(endpointRequest);\n endpointRequest.send(function(err, data) {\n if (err) {\n request.response.error = util.error(err, {\n code: 'EndpointDiscoveryException',\n message: 'Request cannot be fulfilled without specifying an endpoint',\n retryable: false\n });\n } else if (data) {\n AWS.endpointCache.put(cacheKey, data.Endpoints);\n request.httpRequest.updateEndpoint(data.Endpoints[0].Address);\n }\n done();\n });\n } else {\n request.httpRequest.updateEndpoint(endpoints[0].Address);\n done();\n }\n}\n\n/**\n * add api version header to endpoint operation\n * @api private\n */\nfunction addApiVersionHeader(endpointRequest) {\n var api = endpointRequest.service.api;\n var apiVersion = api.apiVersion;\n if (apiVersion && !endpointRequest.httpRequest.headers['x-amz-api-version']) {\n endpointRequest.httpRequest.headers['x-amz-api-version'] = apiVersion;\n }\n}\n\n/**\n * If api call gets invalid endoint exception, SDK should attempt to remove the invalid\n * endpoint from cache.\n * @api private\n */\nfunction invalidateCachedEndpoints(response) {\n var error = response.error;\n var httpResponse = response.httpResponse;\n if (error &&\n (error.code === 'InvalidEndpointException' || httpResponse.statusCode === 421)\n ) {\n var request = response.request;\n var operations = request.service.api.operations || {};\n var inputShape = operations[request.operation] ? operations[request.operation].input : undefined;\n var identifiers = marshallCustomeIdentifiers(request, inputShape);\n var cacheKey = getCacheKey(request);\n cacheKey = util.update(cacheKey, identifiers);\n AWS.endpointCache.remove(cacheKey);\n }\n}\n\n/**\n * If endpoint is explicitly configured, SDK should not do endpoint discovery in anytime.\n * @param [object] clien Service client object.\n * @api private\n */\nfunction hasCustomEndpoint(client) {\n //if set endpoint is set for specific client, enable endpoint discovery will raise an error.\n if (client._originalConfig && client._originalConfig.endpoint && client._originalConfig.endpointDiscoveryEnabled === true) {\n throw util.error(new Error(), {\n code: 'ConfigurationException',\n message: 'If custome endpoint is supplied, endpointDiscoverEnabled should be turned off.'\n });\n };\n var svcConfig = AWS.config[client.serviceIdentifier] || {};\n return AWS.config.endpoint || svcConfig.endpoint || (client._originalConfig && client._originalConfig.endpoint);\n}\n\n/**\n * @api private\n */\nfunction isFalsey(value) {\n return ['false', '0'].indexOf(value) >= 0;\n}\n\n/**\n * If endpoint discovery should perform for this request when endpoint discovery is optional.\n * SDK performs config resolution in order like below:\n * 1. If turned on client configuration(default to off) then turn on endpoint discovery.\n * 2. If turned on in env AWS_ENABLE_ENDPOINT_DISCOVERY then turn on endpoint discovery.\n * 3. If turned on in shared ini config file with key 'endpoint_discovery_enabled', then\n * turn on endpoint discovery.\n * @param [object] request request object.\n * @api private\n */\nfunction isEndpointDiscoveryApplicable(request) {\n var service = request.service || {};\n if (service.config.endpointDiscoveryEnabled === true) return true;\n if (Object.prototype.hasOwnProperty.call(process.env, endpointDiscoveryEnabledEnv)) {\n if (process.env[endpointDiscoveryEnabledEnv] === undefined) {\n throw util.error(new Error(), {\n code: 'ConfigurationException',\n message: 'environmental variable AWS_ENABLE_ENDPOINT_DISCOVERY cannot be set to nothing'\n });\n }\n if (!isFalsey(process.env[endpointDiscoveryEnabledEnv])) return true;\n }\n //shared ini file is only available in Node\n if (util.isBrowser()) return false;",
"repo_full_name": "aws/aws-sdk-js",
"discussion_comments": [
{
"comment_id": "227596555",
"repo_full_name": "aws/aws-sdk-js",
"pr_number": 2253,
"pr_file": "lib/discover_endpoint.js",
"discussion_id": "227596555",
"commented_code": "@@ -0,0 +1,305 @@\n+var AWS = require('./core');\n+var util = require('./util');\n+var ENDPOINT_OPERATION_MAX_RETRIES = 60;\n+var endpointDiscoveryEnabledEnv = 'AWS_ENABLE_ENDPOINT_DISCOVERY';\n+\n+/**\n+ * Generate key to index the endpoints in the cache\n+ * @return [map<String,String>] object with keys to index endpoints.\n+ * @api private\n+ */\n+function getCacheKey(request) {\n+ var service = request.service;\n+ var api = service.api || {};\n+ var operations = api.operations;\n+ var identifiers = {};\n+ if (operations[request.operation] && operations[request.operation].name) {\n+ identifiers.operation = operations[request.operation].name;\n+ }\n+ if (service.config.region) {\n+ identifiers.region = service.config.region;\n+ }\n+ if (api.serviceId) {\n+ identifiers.serviceId = api.serviceId\n+ }\n+ if (service.config.credentials.accessKeyId) {\n+ identifiers.accessKeyId = service.config.credentials.accessKeyId\n+ }\n+ return identifiers;\n+}\n+\n+/**\n+ * @api private\n+ */\n+function marshallCustomeIdentifiersHelper(result, params, shape) {\n+ if (!shape || params === undefined || params === null) return;\n+ if (shape.type === 'structure' && shape.required && shape.required.length > 0) {\n+ util.arrayEach(shape.required, function(name) {\n+ var memberShape = shape.members[name];\n+ if (memberShape.endpointDiscoveryId === true) {\n+ var locationName = memberShape.isLocationName ? memberShape.name : name;\n+ result[locationName] = String(params[name]);\n+ } else {\n+ marshallCustomeIdentifiersHelper(result, params[name], memberShape);\n+ }\n+ });\n+ }\n+}\n+\n+/**\n+ * Get customized cache key according to the 'endpointDiscoveryId' trait.\n+ * @param [object] request object\n+ * @param [object] input shape of the given operation's api\n+ */\n+function marshallCustomeIdentifiers(request, shape) {\n+ var identifiers = {};\n+ marshallCustomeIdentifiersHelper(identifiers, request.params, shape);\n+ return identifiers;\n+}\n+\n+/**\n+ * Call endpoint discovery operation when it's optional.\n+ * When endpoint is available in cache then use the cached endpoints. If endpoints\n+ * are unavailable then use regional endpoints and call endpoint discovery operation\n+ * asynchronously. This is turned off by default.\n+ * @param [object] request object\n+ * @api private\n+ */\n+function optionalDisverEndpoint(request) {\n+ var service = request.service;\n+ var api = service.api;\n+ var operationModel = api.operations ? api.operations[request.operation] : undefined;\n+ var inputShape = operationModel ? operationModel.input : undefined;\n+\n+ var identifiers = marshallCustomeIdentifiers(request, inputShape);\n+ var cacheKey = getCacheKey(request);\n+ cacheKey = util.update(cacheKey, identifiers);\n+ var endpoints = AWS.endpointCache.get(cacheKey);\n+ if (endpoints && endpoints.length > 0) {\n+ //found endpoint record from cache\n+ request.httpRequest.updateEndpoint(endpoints[0].Address);\n+ } else if (endpoints && endpoints.length === 0) {\n+ //endpoint operation is being made but response not yet received\n+ return;\n+ } else {\n+ //endpoint record not in cache. make discovery operation\n+ var endpointRequest = service.makeRequest(api.endpointOperation, {\n+ Operation: operationModel.name,\n+ Identifiers: identifiers,\n+ });\n+ addApiVersionHeader(endpointRequest);\n+ endpointRequest.removeListener('validate', AWS.EventListeners.Core.VALIDATE_PARAMETERS);\n+ endpointRequest.removeListener('retry', AWS.EventListeners.Core.RETRY_CHECK);\n+ var toHead = true;\n+ //if endpoint operation failed, keep retrying every minute.\n+ endpointRequest.on('retry', function(resp) {\n+ var err = resp.error;\n+ err.retryable = true;\n+ err.retryDelay = 60000;\n+ resp.maxRetries = ENDPOINT_OPERATION_MAX_RETRIES;\n+ }, toHead);\n+ //put in a placeholder for endpoints already requested, prevent\n+ //too much in-flight calls\n+ AWS.endpointCache.put(cacheKey, []);\n+ endpointRequest.send(function(err, data) {\n+ if (data && data.Endpoints) {\n+ AWS.endpointCache.put(cacheKey, data.Endpoints);\n+ } else if (err) {\n+ AWS.endpointCache.remove(cacheKey);\n+ }\n+ });\n+ }\n+}\n+\n+/**\n+ * Call endpoint discovery operation when it's required.\n+ * When endpoint is available in cache then use cached ones. If endpoins are\n+ * unavailable then SDK should call endpoint operation end use returned new\n+ * endpoint for the api call. SDK will automatically attempt to do endpoint\n+ * discovery regardless the configuration.\n+ * @param [object] request object\n+ * @api private\n+ */\n+function requiredDiscoverEndpoint(request, done) {\n+ var service = request.service;\n+ var api = service.api;\n+ var operationModel = api.operations ? api.operations[request.operation] : undefined;\n+ var inputShape = operationModel ? operationModel.input : undefined;\n+\n+ var identifiers = marshallCustomeIdentifiers(request, inputShape);\n+ var cacheKey = getCacheKey(request);\n+ cacheKey = util.update(cacheKey, identifiers);\n+ var endpoints = AWS.endpointCache.get(cacheKey);\n+ if (endpoints === undefined || endpoints.length === 0) {\n+ var endpointRequest = service.makeRequest(api.endpointOperation, {\n+ Operation: operationModel.name,\n+ Identifiers: identifiers,\n+ });\n+ endpointRequest.removeListener('validate', AWS.EventListeners.Core.VALIDATE_PARAMETERS);\n+ addApiVersionHeader(endpointRequest);\n+ endpointRequest.send(function(err, data) {\n+ if (err) {\n+ request.response.error = util.error(err, {\n+ code: 'EndpointDiscoveryException',\n+ message: 'Request cannot be fulfilled without specifying an endpoint',\n+ retryable: false\n+ });\n+ } else if (data) {\n+ AWS.endpointCache.put(cacheKey, data.Endpoints);\n+ request.httpRequest.updateEndpoint(data.Endpoints[0].Address);\n+ }\n+ done();\n+ });\n+ } else {\n+ request.httpRequest.updateEndpoint(endpoints[0].Address);\n+ done();\n+ }\n+}\n+\n+/**\n+ * add api version header to endpoint operation\n+ * @api private\n+ */\n+function addApiVersionHeader(endpointRequest) {\n+ var api = endpointRequest.service.api;\n+ var apiVersion = api.apiVersion;\n+ if (apiVersion && !endpointRequest.httpRequest.headers['x-amz-api-version']) {\n+ endpointRequest.httpRequest.headers['x-amz-api-version'] = apiVersion;\n+ }\n+}\n+\n+/**\n+ * If api call gets invalid endoint exception, SDK should attempt to remove the invalid\n+ * endpoint from cache.\n+ * @api private\n+ */\n+function invalidateCachedEndpoints(response) {\n+ var error = response.error;\n+ var httpResponse = response.httpResponse;\n+ if (error &&\n+ (error.code === 'InvalidEndpointException' || httpResponse.statusCode === 421)\n+ ) {\n+ var request = response.request;\n+ var operations = request.service.api.operations || {};\n+ var inputShape = operations[request.operation] ? operations[request.operation].input : undefined;\n+ var identifiers = marshallCustomeIdentifiers(request, inputShape);\n+ var cacheKey = getCacheKey(request);\n+ cacheKey = util.update(cacheKey, identifiers);\n+ AWS.endpointCache.remove(cacheKey);\n+ }\n+}\n+\n+/**\n+ * If endpoint is explicitly configured, SDK should not do endpoint discovery in anytime.\n+ * @param [object] clien Service client object.\n+ * @api private\n+ */\n+function hasCustomEndpoint(client) {\n+ //if set endpoint is set for specific client, enable endpoint discovery will raise an error.\n+ if (client._originalConfig && client._originalConfig.endpoint && client._originalConfig.endpointDiscoveryEnabled === true) {\n+ throw util.error(new Error(), {\n+ code: 'ConfigurationException',\n+ message: 'If custome endpoint is supplied, endpointDiscoverEnabled should be turned off.'\n+ });\n+ };\n+ var svcConfig = AWS.config[client.serviceIdentifier] || {};\n+ return AWS.config.endpoint || svcConfig.endpoint || (client._originalConfig && client._originalConfig.endpoint);\n+}\n+\n+/**\n+ * @api private\n+ */\n+function isFalsey(value) {\n+ return ['false', '0'].indexOf(value) >= 0;\n+}\n+\n+/**\n+ * If endpoint discovery should perform for this request when endpoint discovery is optional.\n+ * SDK performs config resolution in order like below:\n+ * 1. If turned on client configuration(default to off) then turn on endpoint discovery.\n+ * 2. If turned on in env AWS_ENABLE_ENDPOINT_DISCOVERY then turn on endpoint discovery.\n+ * 3. If turned on in shared ini config file with key 'endpoint_discovery_enabled', then\n+ * turn on endpoint discovery.\n+ * @param [object] request request object.\n+ * @api private\n+ */\n+function isEndpointDiscoveryApplicable(request) {\n+ var service = request.service || {};\n+ if (service.config.endpointDiscoveryEnabled === true) return true;\n+ if (Object.prototype.hasOwnProperty.call(process.env, endpointDiscoveryEnabledEnv)) {\n+ if (process.env[endpointDiscoveryEnabledEnv] === undefined) {\n+ throw util.error(new Error(), {\n+ code: 'ConfigurationException',\n+ message: 'environmental variable AWS_ENABLE_ENDPOINT_DISCOVERY cannot be set to nothing'\n+ });\n+ }\n+ if (!isFalsey(process.env[endpointDiscoveryEnabledEnv])) return true;\n+ }\n+ //shared ini file is only available in Node\n+ if (util.isBrowser()) return false;",
"comment_created_at": "2018-10-23T23:12:33+00:00",
"comment_author": "chrisradek",
"comment_body": "Sorry for the incoming tangent, but I have 2 thoughts here.\r\n1. I think we should update `isBrowser` to no longer depend on `process` existing:\r\nhttps://github.com/aws/aws-sdk-js/blob/29fc8d39b73a9c7c15b6bc8fb28cf5ef313691f4/lib/util.js#L39\r\nWe've heard reports of this breaking with Angular, and it doesn't really make sense that we're depending on a global that doesn't exist natively in browsers. Instead, I'd propose we update our (browser|react-native|node)_loader.js files to set the function to return true or false accordingly.\r\n\r\n2. This is less important if we do the item above, but I wonder if it would make sense to separate this function. You could have 3 new functions, each in their own file that perform one of these checks. \r\nThen you could have a separate browser/node file that exports the same function. This function would import whatever checks they need. This has the benefit of your browser build not having to import the code used to check the shared Ini file, and you could then allow the shared ini check to import the shared-ini loader directly. However, it also means more source files and might be more difficult to track.",
"pr_file_module": null
}
]
},
{
"discussion_id": "321824426",
"pr_number": 2838,
"pr_file": "lib/services/sts.js",
"created_at": "2019-09-06T16:57:08+00:00",
"commented_code": "assumeRoleWithSAML: function assumeRoleWithSAML(params, callback) {\n return this.makeUnauthenticatedRequest('assumeRoleWithSAML', params, callback);\n },\n\n /**\n * @api private\n */\n validateRegionalEndpointsFlag: function validateRegionalEndpointsFlag() {\n //validate config value\n var config = this.config;\n if (",
"repo_full_name": "aws/aws-sdk-js",
"discussion_comments": [
{
"comment_id": "321824426",
"repo_full_name": "aws/aws-sdk-js",
"pr_number": 2838,
"pr_file": "lib/services/sts.js",
"discussion_id": "321824426",
"commented_code": "@@ -43,5 +46,87 @@ AWS.util.update(AWS.STS.prototype, {\n \n assumeRoleWithSAML: function assumeRoleWithSAML(params, callback) {\n return this.makeUnauthenticatedRequest('assumeRoleWithSAML', params, callback);\n+ },\n+\n+ /**\n+ * @api private\n+ */\n+ validateRegionalEndpointsFlag: function validateRegionalEndpointsFlag() {\n+ //validate config value\n+ var config = this.config;\n+ if (",
"comment_created_at": "2019-09-06T16:57:08+00:00",
"comment_author": "trivikr",
"comment_body": "This will be more readable if changed to:\r\n\r\n```javascript\r\nif (config.stsRegionalEndpoints) {\r\n if (typeof config.stsRegionalEndpoints === 'string' &&\r\n ['legacy', 'regional'].indexOf(config.stsRegionalEndpoints.toLowerCase()) >= 0) {\r\n // set config.stsRegionalEndpoints and return\r\n } else {\r\n // Throw error\r\n } \r\n}\r\n```",
"pr_file_module": null
}
]
}
]