💾 Archived View for gmi.noulin.net › gitRepositories › git-off › file › src › node_modules › aws-sdk… captured on 2023-01-29 at 11:58:25. Gemini links have been rewritten to link to archived content

View Raw

More Information

-=-=-=-=-=-=-

git-off

Log

Files

Refs

README

service.js (16328B)

     1 var AWS = require('./core');
     2 var Api = require('./model/api');
     3 var regionConfig = require('./region_config');
     4 var inherit = AWS.util.inherit;
     5 var clientCount = 0;
     6 
     7 /**
     8  * The service class representing an AWS service.
     9  *
    10  * @abstract
    11  *
    12  * @!attribute apiVersions
    13  *   @return [Array<String>] the list of API versions supported by this service.
    14  *   @readonly
    15  */
    16 AWS.Service = inherit({
    17   /**
    18    * Create a new service object with a configuration object
    19    *
    20    * @param config [map] a map of configuration options
    21    */
    22   constructor: function Service(config) {
    23     if (!this.loadServiceClass) {
    24       throw AWS.util.error(new Error(),
    25         'Service must be constructed with `new\' operator');
    26     }
    27     var ServiceClass = this.loadServiceClass(config || {});
    28     if (ServiceClass) {
    29       var originalConfig = AWS.util.copy(config);
    30       var svc = new ServiceClass(config);
    31       Object.defineProperty(svc, '_originalConfig', {
    32         get: function() { return originalConfig; },
    33         enumerable: false,
    34         configurable: true
    35       });
    36       svc._clientId = ++clientCount;
    37       return svc;
    38     }
    39     this.initialize(config);
    40   },
    41 
    42   /**
    43    * @api private
    44    */
    45   initialize: function initialize(config) {
    46     var svcConfig = AWS.config[this.serviceIdentifier];
    47 
    48     this.config = new AWS.Config(AWS.config);
    49     if (svcConfig) this.config.update(svcConfig, true);
    50     if (config) this.config.update(config, true);
    51 
    52     this.validateService();
    53     if (!this.config.endpoint) regionConfig(this);
    54 
    55     this.config.endpoint = this.endpointFromTemplate(this.config.endpoint);
    56     this.setEndpoint(this.config.endpoint);
    57   },
    58 
    59   /**
    60    * @api private
    61    */
    62   validateService: function validateService() {
    63   },
    64 
    65   /**
    66    * @api private
    67    */
    68   loadServiceClass: function loadServiceClass(serviceConfig) {
    69     var config = serviceConfig;
    70     if (!AWS.util.isEmpty(this.api)) {
    71       return null;
    72     } else if (config.apiConfig) {
    73       return AWS.Service.defineServiceApi(this.constructor, config.apiConfig);
    74     } else if (!this.constructor.services) {
    75       return null;
    76     } else {
    77       config = new AWS.Config(AWS.config);
    78       config.update(serviceConfig, true);
    79       var version = config.apiVersions[this.constructor.serviceIdentifier];
    80       version = version || config.apiVersion;
    81       return this.getLatestServiceClass(version);
    82     }
    83   },
    84 
    85   /**
    86    * @api private
    87    */
    88   getLatestServiceClass: function getLatestServiceClass(version) {
    89     version = this.getLatestServiceVersion(version);
    90     if (this.constructor.services[version] === null) {
    91       AWS.Service.defineServiceApi(this.constructor, version);
    92     }
    93 
    94     return this.constructor.services[version];
    95   },
    96 
    97   /**
    98    * @api private
    99    */
   100   getLatestServiceVersion: function getLatestServiceVersion(version) {
   101     if (!this.constructor.services || this.constructor.services.length === 0) {
   102       throw new Error('No services defined on ' +
   103                       this.constructor.serviceIdentifier);
   104     }
   105 
   106     if (!version) {
   107       version = 'latest';
   108     } else if (AWS.util.isType(version, Date)) {
   109       version = AWS.util.date.iso8601(version).split('T')[0];
   110     }
   111 
   112     if (Object.hasOwnProperty(this.constructor.services, version)) {
   113       return version;
   114     }
   115 
   116     var keys = Object.keys(this.constructor.services).sort();
   117     var selectedVersion = null;
   118     for (var i = keys.length - 1; i >= 0; i--) {
   119       // versions that end in "*" are not available on disk and can be
   120       // skipped, so do not choose these as selectedVersions
   121       if (keys[i][keys[i].length - 1] !== '*') {
   122         selectedVersion = keys[i];
   123       }
   124       if (keys[i].substr(0, 10) <= version) {
   125         return selectedVersion;
   126       }
   127     }
   128 
   129     throw new Error('Could not find ' + this.constructor.serviceIdentifier +
   130                     ' API to satisfy version constraint `' + version + '\'');
   131   },
   132 
   133   /**
   134    * @api private
   135    */
   136   api: {},
   137 
   138   /**
   139    * @api private
   140    */
   141   defaultRetryCount: 3,
   142 
   143   /**
   144    * @api private
   145    */
   146   customizeRequests: function customizeRequests(callback) {
   147     if (!callback) {
   148       this.customRequestHandler = null;
   149     } else if (typeof callback === 'function') {
   150       this.customRequestHandler = callback;
   151     } else {
   152       throw new Error('Invalid callback type \'' + typeof callback + '\' provided in customizeRequests');
   153     }
   154   },
   155 
   156   /**
   157    * Calls an operation on a service with the given input parameters.
   158    *
   159    * @param operation [String] the name of the operation to call on the service.
   160    * @param params [map] a map of input options for the operation
   161    * @callback callback function(err, data)
   162    *   If a callback is supplied, it is called when a response is returned
   163    *   from the service.
   164    *   @param err [Error] the error object returned from the request.
   165    *     Set to `null` if the request is successful.
   166    *   @param data [Object] the de-serialized data returned from
   167    *     the request. Set to `null` if a request error occurs.
   168    */
   169   makeRequest: function makeRequest(operation, params, callback) {
   170     if (typeof params === 'function') {
   171       callback = params;
   172       params = null;
   173     }
   174 
   175     params = params || {};
   176     if (this.config.params) { // copy only toplevel bound params
   177       var rules = this.api.operations[operation];
   178       if (rules) {
   179         params = AWS.util.copy(params);
   180         AWS.util.each(this.config.params, function(key, value) {
   181           if (rules.input.members[key]) {
   182             if (params[key] === undefined || params[key] === null) {
   183               params[key] = value;
   184             }
   185           }
   186         });
   187       }
   188     }
   189 
   190     var request = new AWS.Request(this, operation, params);
   191     this.addAllRequestListeners(request);
   192 
   193     if (callback) request.send(callback);
   194     return request;
   195   },
   196 
   197   /**
   198    * Calls an operation on a service with the given input parameters, without
   199    * any authentication data. This method is useful for "public" API operations.
   200    *
   201    * @param operation [String] the name of the operation to call on the service.
   202    * @param params [map] a map of input options for the operation
   203    * @callback callback function(err, data)
   204    *   If a callback is supplied, it is called when a response is returned
   205    *   from the service.
   206    *   @param err [Error] the error object returned from the request.
   207    *     Set to `null` if the request is successful.
   208    *   @param data [Object] the de-serialized data returned from
   209    *     the request. Set to `null` if a request error occurs.
   210    */
   211   makeUnauthenticatedRequest: function makeUnauthenticatedRequest(operation, params, callback) {
   212     if (typeof params === 'function') {
   213       callback = params;
   214       params = {};
   215     }
   216 
   217     var request = this.makeRequest(operation, params).toUnauthenticated();
   218     return callback ? request.send(callback) : request;
   219   },
   220 
   221   /**
   222    * Waits for a given state
   223    *
   224    * @param state [String] the state on the service to wait for
   225    * @param params [map] a map of parameters to pass with each request
   226    * @callback callback function(err, data)
   227    *   If a callback is supplied, it is called when a response is returned
   228    *   from the service.
   229    *   @param err [Error] the error object returned from the request.
   230    *     Set to `null` if the request is successful.
   231    *   @param data [Object] the de-serialized data returned from
   232    *     the request. Set to `null` if a request error occurs.
   233    */
   234   waitFor: function waitFor(state, params, callback) {
   235     var waiter = new AWS.ResourceWaiter(this, state);
   236     return waiter.wait(params, callback);
   237   },
   238 
   239   /**
   240    * @api private
   241    */
   242   addAllRequestListeners: function addAllRequestListeners(request) {
   243     var list = [AWS.events, AWS.EventListeners.Core, this.serviceInterface(),
   244                 AWS.EventListeners.CorePost];
   245     for (var i = 0; i < list.length; i++) {
   246       if (list[i]) request.addListeners(list[i]);
   247     }
   248 
   249     // disable parameter validation
   250     if (!this.config.paramValidation) {
   251       request.removeListener('validate',
   252         AWS.EventListeners.Core.VALIDATE_PARAMETERS);
   253     }
   254 
   255     if (this.config.logger) { // add logging events
   256       request.addListeners(AWS.EventListeners.Logger);
   257     }
   258 
   259     this.setupRequestListeners(request);
   260     // call prototype's customRequestHandler
   261     if (typeof this.constructor.prototype.customRequestHandler === 'function') {
   262       this.constructor.prototype.customRequestHandler(request);
   263     }
   264     // call instance's customRequestHandler
   265     if (Object.prototype.hasOwnProperty.call(this, 'customRequestHandler') && typeof this.customRequestHandler === 'function') {
   266       this.customRequestHandler(request);
   267     }
   268   },
   269 
   270   /**
   271    * Override this method to setup any custom request listeners for each
   272    * new request to the service.
   273    *
   274    * @abstract
   275    */
   276   setupRequestListeners: function setupRequestListeners() {
   277   },
   278 
   279   /**
   280    * Gets the signer class for a given request
   281    * @api private
   282    */
   283   getSignerClass: function getSignerClass() {
   284     var version;
   285     if (this.config.signatureVersion) {
   286       version = this.config.signatureVersion;
   287     } else {
   288       version = this.api.signatureVersion;
   289     }
   290     return AWS.Signers.RequestSigner.getVersion(version);
   291   },
   292 
   293   /**
   294    * @api private
   295    */
   296   serviceInterface: function serviceInterface() {
   297     switch (this.api.protocol) {
   298       case 'ec2': return AWS.EventListeners.Query;
   299       case 'query': return AWS.EventListeners.Query;
   300       case 'json': return AWS.EventListeners.Json;
   301       case 'rest-json': return AWS.EventListeners.RestJson;
   302       case 'rest-xml': return AWS.EventListeners.RestXml;
   303     }
   304     if (this.api.protocol) {
   305       throw new Error('Invalid service `protocol\' ' +
   306         this.api.protocol + ' in API config');
   307     }
   308   },
   309 
   310   /**
   311    * @api private
   312    */
   313   successfulResponse: function successfulResponse(resp) {
   314     return resp.httpResponse.statusCode < 300;
   315   },
   316 
   317   /**
   318    * How many times a failed request should be retried before giving up.
   319    * the defaultRetryCount can be overriden by service classes.
   320    *
   321    * @api private
   322    */
   323   numRetries: function numRetries() {
   324     if (this.config.maxRetries !== undefined) {
   325       return this.config.maxRetries;
   326     } else {
   327       return this.defaultRetryCount;
   328     }
   329   },
   330 
   331   /**
   332    * @api private
   333    */
   334   retryDelays: function retryDelays(retryCount) {
   335     return AWS.util.calculateRetryDelay(retryCount, this.config.retryDelayOptions);
   336   },
   337 
   338   /**
   339    * @api private
   340    */
   341   retryableError: function retryableError(error) {
   342     if (this.networkingError(error)) return true;
   343     if (this.expiredCredentialsError(error)) return true;
   344     if (this.throttledError(error)) return true;
   345     if (error.statusCode >= 500) return true;
   346     return false;
   347   },
   348 
   349   /**
   350    * @api private
   351    */
   352   networkingError: function networkingError(error) {
   353     return error.code === 'NetworkingError';
   354   },
   355 
   356   /**
   357    * @api private
   358    */
   359   expiredCredentialsError: function expiredCredentialsError(error) {
   360     // TODO : this only handles *one* of the expired credential codes
   361     return (error.code === 'ExpiredTokenException');
   362   },
   363 
   364   /**
   365    * @api private
   366    */
   367   clockSkewError: function clockSkewError(error) {
   368     switch (error.code) {
   369       case 'RequestTimeTooSkewed':
   370       case 'RequestExpired':
   371       case 'InvalidSignatureException':
   372       case 'SignatureDoesNotMatch':
   373       case 'AuthFailure':
   374       case 'RequestInTheFuture':
   375         return true;
   376       default: return false;
   377     }
   378   },
   379 
   380   /**
   381    * @api private
   382    */
   383   throttledError: function throttledError(error) {
   384     // this logic varies between services
   385     switch (error.code) {
   386       case 'ProvisionedThroughputExceededException':
   387       case 'Throttling':
   388       case 'ThrottlingException':
   389       case 'RequestLimitExceeded':
   390       case 'RequestThrottled':
   391         return true;
   392       default:
   393         return false;
   394     }
   395   },
   396 
   397   /**
   398    * @api private
   399    */
   400   endpointFromTemplate: function endpointFromTemplate(endpoint) {
   401     if (typeof endpoint !== 'string') return endpoint;
   402 
   403     var e = endpoint;
   404     e = e.replace(/\{service\}/g, this.api.endpointPrefix);
   405     e = e.replace(/\{region\}/g, this.config.region);
   406     e = e.replace(/\{scheme\}/g, this.config.sslEnabled ? 'https' : 'http');
   407     return e;
   408   },
   409 
   410   /**
   411    * @api private
   412    */
   413   setEndpoint: function setEndpoint(endpoint) {
   414     this.endpoint = new AWS.Endpoint(endpoint, this.config);
   415   },
   416 
   417   /**
   418    * @api private
   419    */
   420   paginationConfig: function paginationConfig(operation, throwException) {
   421     var paginator = this.api.operations[operation].paginator;
   422     if (!paginator) {
   423       if (throwException) {
   424         var e = new Error();
   425         throw AWS.util.error(e, 'No pagination configuration for ' + operation);
   426       }
   427       return null;
   428     }
   429 
   430     return paginator;
   431   }
   432 });
   433 
   434 AWS.util.update(AWS.Service, {
   435 
   436   /**
   437    * Adds one method for each operation described in the api configuration
   438    *
   439    * @api private
   440    */
   441   defineMethods: function defineMethods(svc) {
   442     AWS.util.each(svc.prototype.api.operations, function iterator(method) {
   443       if (svc.prototype[method]) return;
   444       var operation = svc.prototype.api.operations[method];
   445       if (operation.authtype === 'none') {
   446         svc.prototype[method] = function (params, callback) {
   447           return this.makeUnauthenticatedRequest(method, params, callback);
   448         };
   449       } else {
   450         svc.prototype[method] = function (params, callback) {
   451           return this.makeRequest(method, params, callback);
   452         };
   453       }
   454     });
   455   },
   456 
   457   /**
   458    * Defines a new Service class using a service identifier and list of versions
   459    * including an optional set of features (functions) to apply to the class
   460    * prototype.
   461    *
   462    * @param serviceIdentifier [String] the identifier for the service
   463    * @param versions [Array<String>] a list of versions that work with this
   464    *   service
   465    * @param features [Object] an object to attach to the prototype
   466    * @return [Class<Service>] the service class defined by this function.
   467    */
   468   defineService: function defineService(serviceIdentifier, versions, features) {
   469     AWS.Service._serviceMap[serviceIdentifier] = true;
   470     if (!Array.isArray(versions)) {
   471       features = versions;
   472       versions = [];
   473     }
   474 
   475     var svc = inherit(AWS.Service, features || {});
   476 
   477     if (typeof serviceIdentifier === 'string') {
   478       AWS.Service.addVersions(svc, versions);
   479 
   480       var identifier = svc.serviceIdentifier || serviceIdentifier;
   481       svc.serviceIdentifier = identifier;
   482     } else { // defineService called with an API
   483       svc.prototype.api = serviceIdentifier;
   484       AWS.Service.defineMethods(svc);
   485     }
   486 
   487     return svc;
   488   },
   489 
   490   /**
   491    * @api private
   492    */
   493   addVersions: function addVersions(svc, versions) {
   494     if (!Array.isArray(versions)) versions = [versions];
   495 
   496     svc.services = svc.services || {};
   497     for (var i = 0; i < versions.length; i++) {
   498       if (svc.services[versions[i]] === undefined) {
   499         svc.services[versions[i]] = null;
   500       }
   501     }
   502 
   503     svc.apiVersions = Object.keys(svc.services).sort();
   504   },
   505 
   506   /**
   507    * @api private
   508    */
   509   defineServiceApi: function defineServiceApi(superclass, version, apiConfig) {
   510     var svc = inherit(superclass, {
   511       serviceIdentifier: superclass.serviceIdentifier
   512     });
   513 
   514     function setApi(api) {
   515       if (api.isApi) {
   516         svc.prototype.api = api;
   517       } else {
   518         svc.prototype.api = new Api(api);
   519       }
   520     }
   521 
   522     if (typeof version === 'string') {
   523       if (apiConfig) {
   524         setApi(apiConfig);
   525       } else {
   526         try {
   527           setApi(AWS.apiLoader(superclass.serviceIdentifier, version));
   528         } catch (err) {
   529           throw AWS.util.error(err, {
   530             message: 'Could not find API configuration ' +
   531               superclass.serviceIdentifier + '-' + version
   532           });
   533         }
   534       }
   535       if (!Object.prototype.hasOwnProperty.call(superclass.services, version)) {
   536         superclass.apiVersions = superclass.apiVersions.concat(version).sort();
   537       }
   538       superclass.services[version] = svc;
   539     } else {
   540       setApi(version);
   541     }
   542 
   543     AWS.Service.defineMethods(svc);
   544     return svc;
   545   },
   546 
   547   /**
   548    * @api private
   549    */
   550   hasService: function(identifier) {
   551     return Object.prototype.hasOwnProperty.call(AWS.Service._serviceMap, identifier);
   552   },
   553 
   554   /**
   555    * @api private
   556    */
   557   _serviceMap: {}
   558 });
   559 
   560 ```