node.js request library wrapper and configuration management
Needed a driver for the request library that clearly separated configuration of web service API endpoints from the code that consumed them.
npm install api-client
api-client manages configuration and creation of a set of named api endpoints. Endpoint configuration can be achieved in one of three ways:
In the first two cases, the api-client library expects the config object to have a single attribute, 'endpoints', pointing at a object. The object in turn contains any number endpoint configuration objects as attributes:
endpoints:twitter:type: 'TwitterClient'host: 'api.twitter.com'options:protocol: 'https'other_api:host: 'other.com'
The above configuration object defines configuration of two named endpoints, 'twitter' and 'other_api'. The configurations can be referred to by name when creating instances of ApiClient for sending requests to the web service api. The configuration may specify a 'type' attribute, whose value is the name of a registered or pre-configured api client object.
Each endpoint configuration object has the following layout:
host: 'some.host.com' # The only required attributeport: '232' # Defaults to 80 or 443, depending on the# options.protocol attributetype: 'StringClassName' # Defaults to 'ApiClient'options:protocol: 'http|https' # Either 'http' or 'https', defaults to 'http'base_path: '/apibase' # The base of all url paths for the service, defaults to ''username: 'user' # Defaults to null, use to configure HTTP basic authpassword: 'pass' # Defaults to null, use to configure HTTP basic authversion: 'API_VERSION' # Defaults to null, appended to base_path to form url, onlyrequest_options:timeout: # Defaults to 2000, request fails if it takes longer than this
The request_options object can be used to specify any option allowed by the node.js request library. See https://github.com/mikeal/request.
The url formed by the api-client will therefore be:
require 'api-client'ApiClientload nullconsolelog "Loaded API Client"# Create an instance of TwitterClient.twitter = ApiClientcreate 'twitter'twitteruser_info1'TwitterAPI'include_entities: trueconsolelog "Got Twitter JSON data: " + body
require 'api-client'my_config =endpoints:foo_client:host: 'foo.com'ApiClientload my_configconsolelog "Loaded API Client"foo_client = ApiClientcreate'foo_client'foo_clientget...
require 'api-client': ->consolelog "Foo request: " + @urlApiClientregister'foo'FooClient'FooClient'host: 'foo.com'type: 'FooClient'options:base_path: '/fooapi'consolelog "Registered FooClient, config = " + utilinspectApiClientconfigfc = ApiClientcreate'foo'fctest
The library also exports a subclass of ApiClient called VersionedApiClient that allows automatic handling of an API version in the request path. This is of limited use, because the base_path configuration option can just as well handle it. To use it, provide endpoint config like the following:
endpoints:versioned:type: 'VersionedApiClient'host: 'somehost.com'options:base_path: '/api'version: 'v2'
The api-client library is written to support testing against it by stubbing requests by url regex. Stubs can be set using the configuration mechanism or set explicitly on an instance of the ApiClient class.
endpoints:myclient:type: 'ApiClient'host: 'somehost.com'options:base_path: '/foo'stubs:/.*/nullnull'stub body'
myClient = ApiClientcreate 'myclient'myClientstub_request /.*/nullnull'stub body'
The stub definition consists of an array of four objects:
In either of the above cases, any @get call against the client would result in 'stub body' being returned as the body because the regex would match any url.
The stub body can be either a static string, or an object with a 'file' attribute. In the latter case, the file attribute is the path name of a file whose contents are used as the stub body.
Copyright (c) 2013-14 Douglas A. Seifert