resilient.js Build Status Code Climate NPM Downloads js-standard-style

A reactive HTTP client for node.js and browsers designed for distributed systems, providing fault tolerance capabilities with transparent server fallback, dynamic server discovery (e.g: using Consul), request retry/backoff logic, optional client-side balancing based on empirical server latency and more...

Provides a simple middleware-oriented programmatic API and featured command-line interface. It has been designed to be lightweight (just ~2K SLOC. 9KB gzipped) and dependency free.

To get started, take a look to how does it work, basic usage, examples and API docs.

Resilient is conceptually similar to Ribbon, a Netflix's project.

Contents

Features

  • Reliable failover and error handling with transparent server fallback
  • Smart network error handling covering multiple failure scenarios
  • Smart balancer logic based on empirical server score (network latency, errors and succesfull requests)
  • Transparent request retry cycle attempts on failure (configurable)
  • Discern best servers based on scoring per read and write operations when balancing
  • In/out traffic extensible middleware layer
  • Configurable balancer policy by weight
  • Configurable timeouts, retry loop, cache TTL, fallback behavior...)
  • Avoid fallback/retry cycles per custom HTTP responses codes or verbs
  • Define custom timeouts per HTTP method (e.g permissive for POST/PUT/DELETE, aggressive for GET)
  • Parallel servers discovering for faster availability
  • Built-in support for request/response interceptors (via middleware)
  • Built-in support for servers caching to improve reliability when fallback
  • Configurable external HTTP client to use as forward request proxy (instead of using the embedded one)
  • Dynamic servers auto discovering (based on the resilient specification or via middleware)
  • Able to plug in custom failure strategies to determine if a request was failed or not.
  • Supports promiscuous errors (handles 400-499 codes as fallback errors)
  • Supports pre/post request hooks via event bus API
  • Supports mock/stub working mode via middleware (useful for testing)
  • Reliable HTTP client (it uses internally request and lil-http for the browser)
  • Round robin scheduling algorithm for traffic distribution (experimental)
  • Featured cURL-inspired command-line interface
  • Lightweight library (just ~2K SLOC, 9KB gzipped)
  • Dependency free in browser environments
  • Cross engine. ES5 compliant

Installation

Via npm

npm install resilient

Via Bower

bower install resilient

Via Component

component install resilient-http/resilient.js

Or loading the script remotely

<script src="//cdn.rawgit.com/resilient-http/resilient.js/0.3.4/resilient.js"></script>

Environments

Runs in any ES5 compliant engine.

Node.js Chrome Firefox IE Opera Safari
+0.10 +5 +3.5 +9 +10 +5

Middleware

Framework-specific adapters

Related projects

  • resilient-server - node.js powered dummy HTTP lookup server for testing/development

How to use?

See the basic usage and examples for detailed use cases

How does it work?

The following graph represents from a high-level point of view the internal logic encapsulated in Resilient HTTP client.

Basic usage

If require is available, you must use it to fetch the module. Otherwise it will be available as global exposed as resilient

var Resilient = require('resilient')

Static servers

Define your service servers pool

var servers = [
  'http://api1.server.com',
  'http://api2.server.com',
  'http://api3.server.com'
]

Create a new client and set the servers to balance

var client = Resilient({ service: { basePath: '/api/1.0' }})
client.setServers(servers)

Perform a request (the best available server will be used automatically)

client.get('/users', function (err, res) {
  if (res.status === 200) {
    console.log('Success:', res.data)
  }
})

Dynamic servers lookup

Define the lookup servers pool

var servers = [
  'http://discover1.server.com',
  'http://discover2.server.com',
  'http://discover3.server.com'
]

Create a new client and set the discovering servers

var client = Resilient({ service: { basePath: '/api/1.0' }})
client.discoveryServers(servers)

Finally, perform the request (and that's all, Resilient will take care about everything to reach the best server)

client.get('/users', function (err, res) {
  if (res.status === 200) {
    console.log('Success:', res.data)
  }
})

Note: you could use Consul or other HTTP server using a custom middleware as discovery server. For more information about the Resilient discovery interface, take a look at the documentation

For more usage cases take a look to the examples

Middleware Layer

From version 0.3.x Resilient introduces support for duplex middleware. It essentially provides an interceptor like layer to use external components to augment a specific functionality.

From a high-level point of view it's conceptually similar to an evented API approach, which is commonly used in a event-driven environment with JavaScript, but in this case it's slightly different in terms of flow control nature and relies more in data mutation compared to events.

The significant feature in Resilient middleware layer is that it provides bidirectional control flow for both incoming and outgoing HTTP traffic. This allows you to perform multiple actions before and after a request of a specific type is made by Resilient. This might be considered also as a sort hooks in aspect-oriented programming.

Types of middleware

Since Resilient is divided in two communication live cycle layers, one for the discovery servers and the other one for the service end servers, middleware can be created for both layers:

  • service - Default. Use this type in middleware which are oriented for final servers communication, such as request transformers, autorization...
  • discovery - Use this type in middleware which are oriented only for lookup communication, for instance used as adapter for a lookup server which is not compatible with the Resilient lookup protocol.

Note: the middleware type should be defined a static member of the middleware returned function, using the type property.

Middleware API

Required interface for middleware:

Function([ params ])
  -> Function(options, resilient)
    -> Object{ in: Function(err, res, next), out: Function(option, next) }

For non-duplex middleware you can use the following interface as well:

Function([ params ])
  -> Function(options, resilient)
    -> Function(err, res, next)

An example of a simple middleware implementation:

function testMiddleware(params) {
  // Middleware-specific params
  params = params || {}

  // Do whatever you need here with the params

  // Resilient will pass the Options
  function middleware(options, resilient) {
    // Do whatever you need here with Resilient client options
    // such as defining servers

    return {
      'in': function (err, res, next) {
        // Do something here with the err/response

        next() // Don't forget to call next
      },
      'out': function (options, next) {
        // Do something here with the out HTTP request options

        next() // Don't forget to call next
      }
    }
  }

  middleware.type = 'discovery' // Default to: service

  return middleware
}

An example of middleware usage:

var client = Resilient({
  discovery: {
    servers: ['http://server1', 'http://server2']
  }
})

client.use(testMiddleware({
  custom: 'options',
  key: 'api-key',
  timeout: 3000
}))

client.get('/', function (err, res) {
  // mad science here
})

Command-line interface

For better approach you should install Resilient as global package: npm install -g resilient

Resilient command-line HTTP client
Usage: resilient [url] [options]

Examples:
  resilient http://httpbin.org/user-agent
  resilient --status http://httpbin.org/status/201
  resilient --info http://httpbin.org/status/204
  resilient http://httpbin.org/post -x POST \
            -d '{"hello":"world"}' -h "Content-Type: application/json"
  resilient /api/users -s http://server1.net,http://server2.net
  resilient /api/users -z http://discover1.net,http://discover2.net
  resilient --discover -z http://discover1.net,http://discover2.net --discovery-timeout 500

Options:
  --version, -v            Show the Resilient client version
  --path, -p               Request path
  --servers, -s            Define the service servers (comma separated)
  --method, -x             HTTP method
  --header, -h             Define custom request header
  --data, -d               Value data to send as HTTP request body
  --file, -f               File path to send as HTTP request body
  --retry, -r              Request retry attempts                                       [default: 0]
  --timeout, -t            Request timeout in miliseconds
  --discover, -k           Get an updated list of servers asking for discovery servers
  --discovery-servers, -z  Define the discovery service servers (comma separated)
  --discovery-retry, -R    Discovery servers retry attempts                             [default: 0]
  --discovery-timeout, -T  Discovery servers request maximum timeout in miliseconds
  --info, -i               Show response headers and info
  --info-headers, -I       Show only the response status and headers
  --status, -c             Print the response status code
  --debug, -D              Enable debug mode
  --help, -H               Show help

API

resilient([ options ])

Creates a new resilient client with custom config

Options

The options object supports three different configuration levels

Resilient({
  service: { ... },
  balancer: { ... },
  discovery: { ... }
})

Service

Specific configuration options for the end service servers pool of the Resilient client.

  • servers array<string> - A list of valid servers URIs to reach for the given service. Default null. It's recommended to use discovery servers instead of static service servers
  • retry number - Number of times to retry if all requests failed. Use Infinity for infinitive attemps. Default 0
  • waitBeforeRetry number - Number of milisenconds to wait before start the request retry cycle. Default to 50
  • discoverBeforeRetry boolean - Force to refresh service servers list asking to the discovery servers on each retry attempt. You must define the discovery servers in order to use this feature. Default true
  • promiscuousErrors boolean - Enable promiscuous error handling mode. Client HTTP status errors (400-499) will be treated as failed request, retrying it until it has a valid status (when retry option is enabled). Default false
  • omitRetryWhen array<object> - A collection of rules per method and status code to match in order to omit a request retry cycle. See the usage example. Default null
  • omitFallbackWhen array<object> - A collection of rules per method and status code to match in order to omit a request server fallback. See usage example. Default null
  • omitRetryOnMethods array<string> - Omit a retry cycle attempt if the request method is on the given array. Default null
  • omitFallbackOnMethods array<string> - Omit fallback to the next best available server if current HTTP method is on the given array. If you use this option, retry cycles will be disabled as well for the given methods. Default null
  • omitRetryOnErrorCodes array<number> - Omit a retry cycle attempt if the latest request response status code is one of the given array. Default null
  • omitFallbackOnErrorCodes array<number> - Omit fallback to the next best available server if the latest request response status code is one of the given array. Default null
  • timeouts object - Define custom request timeout values in miliseconds per HTTP method, useful to differ read/write requests. This option has priority over the timeout option. Default: null

Specific shared configuration options for the HTTP client for final service requests

  • path string - Server request path as part of the final URL
  • basePath string - Server resource base path to share between all requests
  • method string - Request HTTP method. Default to GET
  • data mixed - Payload data to send as body request
  • headers object - Map of strings representing HTTP headers to send to the server
  • params object - Map of strings representing the query params
  • timeout number - Request maximum timeout in miliseconds before to abort it. Default to 10 seconds
  • auth object - Authentication credentials to the server. Object must have both user and password properties

Browser specific options

  • withCredentials boolean - Whether to set the withCredentials flag on the XHR object. See MDN for more information
  • responseType string - Define how to handle the response data. Allowed values are: text, arraybuffer, blob or document

Node.js specific options

See all HTTP options supported for node.js here

Balancer

  • enable boolean - Enable/disable the smart client balancer. Default to true.
  • random boolean - Use random balance strategy using Math.random(). Default to false.
  • balanceStrategy function - Custom balance strategy function. Interface to be implemented: function (servers []Server) => []Server. Default to null.
  • disableWeight boolean - Disable emphirical built-in weight calculus based on server stats for balancing (latency, errors, success).
  • roundRobin boolean - Enable RobinRobin schedule algorithm (experimental). Default: false.
  • roundRobinSize number - Round robin round size. Useful to increase requests distribution across different servers. Default to 3 servers.
  • weight object - Balacer calculus percentage weight used for best available server scoring policy:
    • success number - Percentage weight for success request. Default to 15.
    • error number - Percentage weight for failed request. Default to 50.
    • latency number - Percentage weight for request average latency. Default to 35.

Discovery

Specific configuration for discovery servers requests, behavior and logic

  • servers array<string> - A list of valid server URIs to use as discovery servers
  • cacheEnabled boolean - Enable/disable discovery servers cache in case of global fallback. Useful to improve client reliability. Default true
  • cacheExpiration number - Maximum cache time to live. Default to 10 minutes
  • retry number - Number of times to retry if all requests failed. Use Infinity for infinitive attemps. Default 3
  • waitBeforeRetry number - Number of milisenconds to wait before start the request retry cycle. Default to 1000
  • parallel boolean - Discover servers in parallel. This will improve service availability and decrement server lookup delays. Default true
  • refreshInterval number - Servers list time to live in miliseconds. Default to 2 minutes
  • enableRefreshServers boolean - Enable/disable discovery servers auto refresh. This option requires refreshServers or enableSelfRefresh has been defined. Default true
  • refreshServers array - Servers list of refresh servers. This will enable automatically update discovery servers list asking for them selves to the following list of servers on each interval. Default null
  • refreshServersInterval number - Discovery servers list time to live in miliseconds. Default to 5 minutes
  • enableSelfRefresh boolean - Enable/disable self-discovery using the discovery servers pools. This requires the refreshPath option has been defined. Default false
  • forceRefreshFirst boolean - Enable/disable forcing to refresh the server on the first request. This requires the refreshPath and enableRefreshServers options has been defined. Default true
  • refreshPath string - Discovery refresh servers lookup path. Example: /app/name. This options requires you define enableSelfRefresh to true. Default null
  • refreshOptions object - Custom HTTP options for discovery servers refresh. By default inherits from discovery options
  • promiscuousErrors boolean - Enable promiscuous error handling mode. Client HTTP status errors (400-499) will be treated as failed request, retrying it until it has a valid status (when retry option is enabled). Default false
  • omitRetryWhen array<object> - A collection of rules per method and status code to match in order to omit a request retry cycle. See the usage example. Default null
  • omitFallbackWhen array<object> - A collection of rules per method and status code to match in order to omit a request server fallback. See usage example. Default null
  • omitRetryOnMethods array<string> - Omit a retry cycle attempt if the request HTTP method is on the given array. Default null
  • omitFallbackOnMethods array<string> - Omit fallback to the next best available server if the HTTP method is on the given array. If you use this option, retry cycles will be disabled as well for the given methods. Default null
  • omitRetryOnErrorCodes array<number> - Omit a retry cycle attempt if the latest request response status code is one of the given array. Default null
  • omitFallbackOnErrorCodes array<number> - Omit fallback to the next best available server if the latest request response status code is one of the given array. Default null
  • timeouts object - Define custom request timeout values in miliseconds per HTTP method, useful to differ read/write requests. This option has priority over the timeout option. Default: null

Specific shared configuration options for the HTTP client for discovering processes

  • path string - Server request path as part of the final URL
  • basePath string - Server resource base path to share between all requests
  • timeout number - Server discovery network timeout in miliseconds. Default 2 seconds
  • auth object - Authentication credentials required for the discovery server. Object must have both user and password properties
  • params object - Map of strings representing the query params
  • headers object - Map of strings representing HTTP headers to send to the discovery server
  • method string - Request HTTP method. Default to GET
  • data mixed - Optional data to send as payload to discovery servers. Default null

For node.js, see all HTTP options supported here

Request callback arguments

Response

Browser
  • data mixed - Body response. If the MIME type is JSON-compatible, it will be transparently parsed
  • status number - HTTP response status code
  • headers object - Response headers
  • xhr object - Original XHR instance
  • error mixed - Error info, usually an Error instance (in case that an error happens)
Node.js

See http.IncomingMessage

Error

It could be an Error or plain Object instance with the following members

  • message string - Human readable error message description
  • status number - Internal error code or server HTTP response status
  • code number - Optional error code (node.js only)
  • stack string - Optional stack error trace
  • request object - Original response object in case that a custom Resilient error happends. Optional
  • error Error - Original throwed Error instance (node.js only). Optional
  • xhr XMLHttpRequest - XHR native instance (browser only)
Built-in error codes
  • 1000 - All requests failed. No servers available
  • 1001 - Cannot update discovery servers. Empty or invalid response body
  • 1002 - Missing discovery servers. Cannot resolve the server
  • 1003 - Cannot resolve servers. Missing data
  • 1004 - Discovery server response is invalid or empty
  • 1005 - Missing servers during retry process
  • 1006 - Internal state error (usually caused by an unexpected exception)
  • 1007 - Error injected via middleware

Events

Resilient client has a built-in support for internal states event dispacher and notifier to the public interface

This could be really useful while using an interceptor pattern in order to detect different states and data changes. You can intercept and change any both request and response objects subscribing to the pre/post request hooks. Note that mutation is required, you should modify the object by reference and do not lose it

// subscribe to every outgoing request before be dropped to the network
resilientClient.on('request:start', function handler(options, resilient) {
  // mutate the options, adding an aditional header
  options.headers['API-Token'] = 'awesome!'
  // unsubscribe example
  resilientClient.off('request:start', handler)
})
request:start

Arguments: options<Object>, resilient<Resilient>

Fired before a request is created

You can intercept and modify the request options on the fly, but you must mutate the options object

request:outgoing

Arguments: options<Object>, resilient<Resilient>

Fired every time before a HTTP request is sent via network

You can intercept and modify the request options on the fly, but you must mutate the options object

request:incoming

Arguments: error<Error>, response<Object|http.IncomingMessage>, options<Object>, resilient<Resilient>

Fired every time a HTTP response is received from a server

request:finish

Arguments: error<Error>, response<Object|http.IncomingMessage>, resilient<Resilient>

Fired after a request was completed

You can intercept and modify the error/response on the fly, but you must mutate the object

request:retry

Arguments: options<Object>, servers<Servers>

Fired when a request performs a retry attempt cycle, that means all the previous requests has failed

request:fallback

Arguments: options<Object>, response<Object>

Fired when any request (service or discovery) to a given server fails and therefore tries to perform the next server fallback

servers:refresh

Arguments: servers<Array>, resilient<Resilient>

Fired every time that service servers list is updated from discovery servers

servers:cache

Arguments: servers<Array>, resilient<Resilient>

Fired every time that servers cache is updated

discovery:refresh

Arguments: servers<Array>, resilient<Resilient>

Fired every time that discovery servers are updated form refresh servers

Methods

resilient#send(path, options, callback)

Performs a custom request with the given options. It's recommended using as generic interface to make multi verb requests

resilient#get(path, options, callback)

Return Client

Creates a GET request with optional custom options

resilient#post(path, options, callback)

Return Client

Creates a POST request with optional custom options Return Client

resilient#put(path, options, callback)

Return Client

Creates a PUT request with optional custom options

resilient#delete(path, options, callback)

Alias: del | Return Client

Creates a DELETE request with optional custom options

resilient#patch(path, options, callback)

Return Client

Creates a PATCH request with optional custom options

resilient#head(path, options, callback)

Return Client

Creates a HEAD request with optional custom options

resilient#options([ type|options, options ])

Getter/setter accessor for resilient options, optionally per type. See supported options

resilient#serviceOptions([ options ])

Getter/setter accessor for service-level config options

resilient#discoveryOptions([ options ])

Getter/setter accessor for discovery-level config options

resilient#balancer([ options ])

Return: object

Getter/Setter accessor for balancer-level config options

resilient#httpOptions(type)

Return: object

Get a map of HTTP specific options

resilient#addFailStrategy(strategy)

Alias: failStrategy

Add a custom failure evaluator function strategy in order to determine if Resilient should handle the request as failed or success status, retrying it accordingly if required.

Strategies should return a boolean value indicating if the request failed (true) or not (false).

Use example:

var resilient = require('resilient')

var client = resilient()

client.addFailStrategy(function limitReached(err, res) {
  return !err
    && +res.headers['x-ratelimit-remaining'] === 0
})

resilient#areServersUpdated()

Return: boolean

Returns true if servers are up-to-date. Otherwise false

resilient#servers([ type = 'service' ])

Return: Servers

Return a Servers instance with the current used servers per type. Allowed types are: service and discovery

resilient#serversURL([ type = 'service' ])

Return: array<string>

Return an array of server URLs for the given type. Allowed types are: service and discovery

resilient#resetScore([ type = 'service' ])

Return: Resilient Alias: resetStats

Reset servers stats score based on network latency and percentage of success and failed requests

This score is the average calculus of the total amount of sent requests from the client to each server. This score is used in the scheduling algorithm in order to determinate the best available server (in the case that the balance option is enabled)

Allowed types are: service and discovery

resilient#discoveryServers([ servers ])

Return: Servers

Setter/Getter for discovery servers list

resilient#discoverServers([ options, ] cb)

Return: Resilient

Pass to the callback an up-to-date list of servers asking to discovery servers

Passed arguments to the callback are:

  • error object - Error, if it happend
  • servers array - Array of string with the current service servers URL

resilient#latestServers([ options, ] cb)

Return: Resilient Alias: getUpdatedServers

Pass to the callback an up-to-date list of servers, with or without discovery servers configured

Passed arguments to the callback are:

  • error object - Error, if it happend
  • servers array - Array of string with the current service servers URL

resilient#updateServers([ options, ] cb)

Force to update the servers list from discovery servers, if they are defined, optionally passing a callback to handle the result

Passed arguments to the callback are:

  • error object - Error, if it happend
  • servers array - Array of string with the current service servers URL

resilient#use(middleware)

Register a new middleware. See the middleware documentation or examples for more information

resilient#useHttpClient(fn)

Use a custom HTTP client as proxy instead of the embedded resilient native HTTP client.

Useful to define use proxy for custom frameworks or libraries in your existent project when you need to deal with some complex HTTP pre/post hooks logic and exploit custom HTTP client features

If defined, all the outgoing requests through Resilient client will be proxied to it.

Arguments passed to the client function:

  • options object - Resilient HTTP service options
  • callback function - Request status handler. Expected arguments are: error, response

Note: error and response objects must be compatible with the current interface

resilient#restoreHttpClient()

Restore the native resilient HTTP client

resilient#mock(mockFn)

Define a mock/fake HTTP client error/response object for all outgoing requests

resilient.mock(function (options, cb) {
  if (options.url === 'http://discovery.server.me') {
    // fake response
    cb(null, { status: 200, data: ['http://server.net'] })
  } else {
    // fake unavailable status
    cb(null, { status: 503 })
  }
})

See also the useHttpClient() method for custom request proxy forward, also useful for testing with stubs/fakes

resilient#unmock()

Disable the mock/fake mode

resilient#on(event, handler)

Subscribe to an event. See supported events

resilient#off(event, handler)

Unsubscribe a given event and its handler. See supported events

resilient#once(event, handler)

Subscribe to an event with a given handler just once time. After fired, the handler will be removed

See supported events

resilient#cache.flush()

Force to flush servers cache

resilient#client()

Return: Client Alias: http

Returns an HTTP client-only interface. Useful to provide encapsulation from public usage and avoid resilient-specific configuration methods to be called from the public API.

This is a restricted API useful to provide for high-level developers

resilient.VERSION

Type: string

Current semver library version

resilient.CLIENT_VERSION

Type: string

Current semver HTTP client library version

It uses request in node.js and lil-http in the browser

resilient.defaults

Type: object

Default config options

resilient.Options(options)

Create a new options store

resilient.Client(resilient)

Creates a new resilient HTTP client with public API

Useful to provide encapsulation to the resilient API and expose only the HTTP client (the common interface the developers want to consum)

resilient.request(options [, cb])

Use the plain HTTP client (request in node.js and lil-http in the browser)

FAQ

It's required to have discovery servers in my infraestructure in order to use Resilient?

Definitely not. Discovery servers only will be used in the case that you configure them in your Resilient client. In that case Resilient will simply use the the static service servers to communicate with your backend

Can I use Resilient as a simple HTTP client without balancing?

Yes. If your perform a request with a full URI schema, Resilient will treat it as plain request without applying any internal logic:

var client = Resilient({
  service: {
    servers: ['http://server1.me', 'http://server2.me']
  }
})

// direct plain request (no balancing, no discovery, no fallback...)
client.get('http//custom.server/hello', function (err, res) {
  // ...
})

// resilient powered request (with balancing, fallback, discovery server, cache...)
client.get('/hello', function (err, res) {
  // ...
})

Can I use a custom HTTP client instead of the embedded one?

Of course you can do it. In browser environments this is a common premise, for example you need to use the custom HTTP client of the framework you are using in your application, or a custom library like zepto or jQuery that provides a simple AJAX interface

You can do that defining a function middleware to act as proxy pattern to intercept and wrap all the HTTP traffic via the Resilient client

var client = Resilient({})
// example using Zepto.js AJAX interface
client.useHttpClient(function httpProxy(options, cb) {
  options.success = function (data, status, xhr) {
    cb(null, { status: xhr.status, data: data, xhr: xhr })
  }
  options.error = function (xhr) {
    cb({ status: xhr.status, xhr: xhr })
  }
  $.ajax(options)
})

For more information, see the API method documentation

Can I use streams?

Not yet. There are plans to support it in future versions.

Can I use Resilient in production projects?

Resilient was used in both web and node.js production applications.

The library is, indeed, relatively young and it will evolve with new features in future versions (in fact a full core and logic redesign is required), but the API consistency in not compromised between patch minor releases.

How can I create custom middleware?

You can see the middleware documentation or see an example

Contributing

Wanna help? Cool! It will be appreciated :)

You must add new test cases for any new feature or refactor you do, always following the same design/code patterns that already exist

Development

Only node.js is required for development

Clone the repository

$ git clone https://github.com/resilient-http/resilient.js.git && cd resilient.js

Install development dependencies

$ npm install

Install browser dependencies

$ bower install

Generate browser bundle source

$ make browser

Run tests (in both node.js and headless browser)

$ make test

Run tests in real browsers

$ make test-browser

License

MIT © Tomas Aparicio and contributors



resilient.js Build Status Code Climate NPM Downloads js-standard-style

反应式 HTTP客户端,用于 node.js 浏览器设计用于分布式系统,通过透明 >服务器回退,动态服务器发现(例如:使用Consul),请求重试 / 退货逻辑,可选客户端根据经验性服务器延迟和更多

平衡

提供一个简单的面向中间件的程式API ,并提供了命令行界面。它被设计为轻量级(只有〜2K的SLOC。9KB gzipped)和依赖关系。

要开始使用,请查看它的工作原理基本用法示例 API docs。

弹性在概念上类似于功能区,Netflix的项目。

目录

功能

  • 透明服务器后备可靠的故障切换和错误处理
  • 涉及多种故障情况的智能网络错误处理
  • 基于实证服务器分数(网络延迟,错误和成功请求)的智能平衡器逻辑
  • 透明请求重试循环尝试失败(可配置)
  • 在平衡
  • 时,根据每次读写操作的评分来辨别最佳服务器 进/出流量可扩展中间件层
  • 可重构的平衡器策略
  • 可配置超时,重试循环,缓存TTL,回退行为…)
  • 避免每个自定义HTTP响应代码或动词的回退/重试周期
  • 定义每个HTTP方法的自定义超时(例如,允许POST / PUT / DELETE,对GET有攻击性)
  • 并发服务器发现更快的可用性
  • 内置对请求​​/响应拦截器的支持(通过中间件)
  • 内置支持服务器缓存,以便在后退时提高可靠性
  • 可配置的外部HTTP客户端用作转发请求代理(而不是使用嵌入式客户端)
  • 动态服务器自动发现(基于弹性的规范或通过中间件)
  • 能够插入自定义失败策略,以确定请求是否失败。
  • 支持混杂错误(处理400-499个代码作为备用错误)
  • 通过事件总线API
  • 支持前/后请求挂钩
  • 通过中间件支持模拟/存根工作模式(用于测试)
  • 可靠的HTTP客户端(内部使用请求 lil-http
  • 流量分配的循环调度算法(实验)
  • 精选cURL灵感的命令行界面
  • 轻量级库(只需〜2K SLOC,9KB gzipped)
  • 浏览器环境中的依赖关系
  • 交叉引擎。符合ES5标准

安装

通过 npm

npm install resilient

通过 Bower

bower install resilient

通过组件

component install resilient-http/resilient.js

或远程加载脚本

<script src="//cdn.rawgit.com/resilient-http/resilient.js/0.3.4/resilient.js"></script>

环境

运行在任何符合ES5的引擎。

Node.js Chrome Firefox IE Opera Safari
+0.10 +5 +3.5 +9 +10 +5

中间件

框架特定适配器

  • 角度弹性 - 将$ http变成具有弹性且容错客户端

相关项目

如何使用?

请参阅基本用法示例用于详细的用例

它如何工作?

下图显示了从高级角度看,内部逻辑封装在Resilient HTTP客户端中。

< / p>

基本用法

如果 require 可用,您必须使用它来获取模块。 否则它将作为全局暴露为弹性

可用
var Resilient = require('resilient')

Static servers

定义您的服务器池

创建一个新的客户端,并将服务器设置为平衡

var client = Resilient({ service: { basePath: '/api/1.0' }})
client.setServers(servers)

执行请求(将自动使用最佳可用服务器)

client.get('/users', function (err, res) {
  if (res.status === 200) {
    console.log('Success:', res.data)
  }
})

Dynamic servers lookup

定义查找服务器池

创建新客户端并设置发现服务器

var client = Resilient({ service: { basePath: '/api/1.0' }})
client.discoveryServers(servers)
最后,执行请求(所有这一切,Resilient将会关心所有事情以达到最佳的服务器)

client.get('/users', function (err, res) {
  if (res.status === 200) {
    console.log('Success:', res.data)
  }
})

注意:您可以使用领事馆或其他HTTP服务器,使用自定义中间件作为发现服务器。有关Resilient发现界面的更多信息,请查看文档

有关更多使用情况,请查看示例

中间件层

从版本 0.3.x Resilient引入了对双工中间件的支持。 它本质上提供了一个类似拦截器的层,以使用外部组件来增加特定的功能。

从高层次来看,它在概念上类似于事件驱动的JavaScript环境中常用的事件API方法, 但在这种情况下,在流量控制性质方面略有不同,与事件相比,数据突变更多 弹性中间件层中的重要功能是为传入和传出HTTP流量提供双向控制流。 这允许您在Resilient进行特定类型的请求之前和之后执行多个操作。这可能也被认为是面向方面编程中的一个排序钩子。

中间件的类型

由于Resilient分为两个通信实时循环层,一个用于发现服务器,另一个用于服务终端服务器,可以为两个层创建中间件:

  • 服务 - 默认。在中间件中使用此类型,面向最终服务器通信,例如请求变压器,自动化…
  • 发现 - 在仅用于查找通信的中间件中使用此类型,例如用作与Resilient不兼容的查找服务器的适配器lookup协议

注意:中间件类型应定义为中间件返回函数的静态成员,使用类型属性。

Middleware API

中间件需要的接口:

Function([ params ])
  -> Function(options, resilient)
    -> Object{ in: Function(err, res, next), out: Function(option, next) }

对于非双工中间件,您还可以使用以下界面:

Function([ params ])
  -> Function(options, resilient)
    -> Function(err, res, next)

简单中间件实现的一个例子:

function testMiddleware(params) {
  // Middleware-specific params
  params = params || {}

// Do whatever you need here with the params

// Resilient will pass the Options function middleware(options, resilient) { // Do whatever you need here with Resilient client options // such as defining servers

<span class="pl-k">return</span> {
  <span class="pl-s"><span class="pl-pds">&#39;</span><span class="pl-en">in</span><span class="pl-pds">&#39;</span></span><span class="pl-k">:</span> <span class="pl-k">function</span> (<span class="pl-smi">err</span>, <span class="pl-smi">res</span>, <span class="pl-smi">next</span>) {
    <span class="pl-c"><span class="pl-c">//</span> Do something here with the err/response</span>

    <span class="pl-en">next</span>() <span class="pl-c"><span class="pl-c">//</span> Don&#39;t forget to call next</span>
  },
  <span class="pl-s"><span class="pl-pds">&#39;</span><span class="pl-en">out</span><span class="pl-pds">&#39;</span></span><span class="pl-k">:</span> <span class="pl-k">function</span> (<span class="pl-smi">options</span>, <span class="pl-smi">next</span>) {
    <span class="pl-c"><span class="pl-c">//</span> Do something here with the out HTTP request options</span>

    <span class="pl-en">next</span>() <span class="pl-c"><span class="pl-c">//</span> Don&#39;t forget to call next</span>
  }
}

}

middleware.type = 'discovery' // Default to: service

return middleware }

中间件使用示例:

var client = Resilient({
  discovery: {
    servers: ['http://server1', 'http://server2']
  }
})

client.use(testMiddleware({ custom: 'options', key: 'api-key', timeout: 3000 }))

client.get('/', function (err, res) { // mad science here })

命令行界面

为了更好的方法,您应该将 Resilient 安装为全局包: npm install -g elastic

Resilient command-line HTTP client
Usage: resilient [url] [options]

Examples: resilient http://httpbin.org/user-agent resilient –status http://httpbin.org/status/201 resilient –info http://httpbin.org/status/204 resilient http://httpbin.org/post -x POST
-d '{"hello":"world"}' -h "Content-Type: application/json" resilient /api/users -s http://server1.net,http://server2.net resilient /api/users -z http://discover1.net,http://discover2.net resilient –discover -z http://discover1.net,http://discover2.net –discovery-timeout 500

Options: –version, -v Show the Resilient client version –path, -p Request path –servers, -s Define the service servers (comma separated) –method, -x HTTP method –header, -h Define custom request header –data, -d Value data to send as HTTP request body –file, -f File path to send as HTTP request body –retry, -r Request retry attempts [default: 0] –timeout, -t Request timeout in miliseconds –discover, -k Get an updated list of servers asking for discovery servers –discovery-servers, -z Define the discovery service servers (comma separated) –discovery-retry, -R Discovery servers retry attempts [default: 0] –discovery-timeout, -T Discovery servers request maximum timeout in miliseconds –info, -i Show response headers and info –info-headers, -I Show only the response status and headers –status, -c Print the response status code –debug, -D Enable debug mode –help, -H Show help

API

elastic([options] )

使用自定义配置

创建一个新的弹性客户端

选项

选项 object 支持三种不同的配置级别

Resilient({
  service: {  },
  balancer: {  },
  discovery: {  }
})

Service

弹性客户端的最终服务服务器池的具体配置选项。

  • servers array&lt; string&gt; - 给定服务的有效服务器URI列表。默认 null 。建议使用发现服务器而不是静态服务服务器
  • 重试 number - 如果所有请求失败,重试次数。使用 Infinity 作为不定式的attemps。默认 0
  • waitBeforeRetry number - 开始请求重试循环之前等待的milisenconds数。默认为 50
  • discoverBeforeRetry boolean - 强制刷新服务服务器列表,在每次重试尝试时询问发现服务器。您必须定义发现服务器才能使用此功能。默认 true
  • promiscuousErrors boolean - 启用混杂错误处理模式。客户端HTTP状态错误(400-499)将被视为失败的请求,重试它直到它具有有效的状态(启用 retry 选项时)。默认 false
  • omitRetryWhen array&lt; object&gt; - 为了省略请求重试周期,每个方法和状态代码的规则集合要匹配。请参阅示例的用法。默认 null
  • omitFallbackWhen array&lt; object&gt; - 每个方法和状态代码的一组规则,以匹配以省略请求服务器后备。请参阅示例。默认 null
  • omitRetryOnMethods array&lt; string&gt; - 如果请求方法在给定的数组上,则忽略重试循环尝试。默认 null
  • omitFallbackOnMethods array&lt; string&gt; - 如果当前HTTP方法在给定的数组上,则将后退到下一个最佳可用服务器。如果使用此选项,对于给定的方法,重试周期也将被禁用。默认 null
  • omitRetryOnErrorCodes array&lt; number&gt; - 如果最新的请求响应状态代码是给定的数组之一,则忽略重试循环尝试。默认 null
  • omitFallbackOnErrorCodes array&lt; number&gt; - 如果最新的请求响应状态代码是给定的数组之一,则将后退到下一个最佳可用服务器。默认 null
  • 超时 对象 - 定义每个HTTP方法的自定义请求超时值,以毫秒为单位,对读/写请求的不同有用。此选项优先于 timeout 选项。默认值: null

用于最终服务请求的HTTP客户端的特定共享配置选项

  • 路径 string - 服务器请求路径作为最终URL的一部分
  • basePath string - 所有请求之间共享的服务器资源基础路径
  • 方法 string - 请求HTTP方法。默认为 GET
  • 数据 混合 - 以身份请求发送的有效数据
  • 标头 对象 - 表示要发送到服务器的HTTP标头的字符串映射
  • params object - 表示查询参数的字符串映射
  • timeout number - 请求以超时的最大超时时间中止它。默认为 10
  • auth 对象 - 服务器的身份验证凭据。对象必须同时具有用户密码属性

浏览器特定选项

  • withCredentials boolean - 是否在XHR对象上设置withCredentials标志。有关详细信息,请参见 MDN
  • responseType string - 定义如何处理响应数据。允许的值是: text arraybuffer blob 文档

Node.js特定选项

查看支持 node.js 的所有HTTP选项此处

Balancer

  • 启用 布尔值 - 启用/禁用智能客户端平衡器。默认为 true
  • random boolean - 使用 Math.random()使用随机平衡策略。默认为 false
  • balanceStrategy function - 自定义平衡策略功能。要实现的接口: function(servers [] Server)=&gt; []服务器。默认为 null
  • disableWeight boolean - 根据服务器统计信息(延迟,错误,成功)禁用emphirical内置权重演算。
  • roundRobin boolean - 启用RobinRobin调度算法(实验)。默认值: false
  • roundRobinSize number - 循环轮的大小。有助于增加不同服务器之间的请求分配。默认为 3 服务器。
  • weight object - 用于最佳可用服务器评分策略的Balacer演算百分比权重:
    • 成功 number - 成功请求的重量百分比。默认为 15
    • 错误 number - 失败请求的重量百分比。默认为 50
    • 延迟 number - 请求平均延迟的百分比权重。默认为 35

Discovery

发现服务器请求,行为和逻辑的具体配置

  • servers array&lt; string&gt; - 用作发现服务器的有效服务器URI列表
  • cacheEnabled boolean - 在全局后备的情况下启用/禁用发现服务器缓存。有助于提高客户的可靠性。默认 true
  • cacheExpiration number - 最大缓存生存时间。默认为 10 minutes
  • 重试 number - 如果所有请求失败,重试次数。使用 Infinity 作为不定式的attemps。默认 3
  • waitBeforeRetry number - 开始请求重试循环之前等待的milisenconds数。默认为 1000
  • 并行 布尔值 - 并行发现服务器。这将提高服务可用性并减少服务器查找延迟。默认 true
  • refreshInterval number - 服务器列出以毫秒为单位的时间。默认为 2 分钟
  • enableRefreshServers boolean - 启用/禁用发现服务器自动刷新。此选项需要定义 refreshServers enableSelfRefresh 。默认 true
  • refreshServers array - 刷新服务器的服务器列表。这将允许自动更新发现服务器列表,以便在每个间隔中自动向以下服务器列表。默认 null
  • refreshServersInterval number - 发现服务器列出以毫秒为单位的时间。默认为 5 分钟
  • enableSelfRefresh boolean - 使用发现服务器池启用/禁用自我发现。这需要定义 refreshPath 选项。默认 false
  • forceRefreshFirst boolean - 启用/禁用强制在第一个请求上刷新服务器。这需要定义 refreshPath enableRefreshServers 选项。默认 true
  • refreshPath string - 发现刷新服务器查找路径。示例: / app / name 。此选项需要您将 enableSelfRefresh 定义为 true 。默认 null
  • refreshOptions 对象 - 发现服务器刷新的自定义HTTP选项。默认情况下,继承自发现选项
  • promiscuousErrors boolean - 启用混杂错误处理模式。客户端HTTP状态错误(400-499)将被视为失败的请求,重试它直到它具有有效的状态(启用 retry 选项时)。默认 false
  • omitRetryWhen array&lt; object&gt; - 为了省略请求重试周期,每个方法和状态代码的规则集合要匹配。请参阅示例的用法。默认 null
  • omitFallbackWhen array&lt; object&gt; - 每个方法和状态代码的一组规则,以匹配以省略请求服务器后备。请参阅示例。默认 null
  • omitRetryOnMethods array&lt; string&gt; - 如果请求HTTP方法在给定的数组上,则忽略重试循环尝试。默认 null
  • omitFallbackOnMethods array&lt; string&gt; - 如果HTTP方法在给定的数组上,则将后退到下一个最佳可用服务器。如果使用此选项,对于给定的方法,重试周期也将被禁用。默认 null
  • omitRetryOnErrorCodes array&lt; number&gt; - 如果最新的请求响应状态代码是给定的数组之一,则忽略重试循环尝试。默认 null
  • omitFallbackOnErrorCodes array&lt; number&gt; - 如果最新的请求响应状态代码是给定的数组之一,则将后退到下一个最佳可用服务器。默认 null
  • 超时 对象 - 定义每个HTTP方法的自定义请求超时值,以毫秒为单位,对读/写请求的不同有用。此选项优先于 timeout 选项。默认值: null

用于发现进程的HTTP客户端的特定共享配置选项

  • 路径 string - 服务器请求路径作为最终URL的一部分
  • basePath string - 所有请求之间共享的服务器资源基础路径
  • timeout number - 以毫秒为单位的服务器发现网络超时。默认 2
  • auth 对象 - 发现服务器所需的身份验证凭据。对象必须同时具有用户密码属性
  • params object - 表示查询参数的字符串映射
  • 标头 对象 - 表示要发送到发现服务器的HTTP头的字符串映射
  • 方法 string - 请求HTTP方法。默认为 GET
  • 数据 混合 - 作为有效载荷发送到发现服务器的可选数据。默认 null

对于 node.js ,请参阅所有支持的HTTP选项此处

请求回调参数

Response

Browser
  • 数据 混合 - 身体反应。如果MIME类型为 JSON兼容,则将透明地解析
  • 状态 number - HTTP响应状态代码
  • 标头 对象 - 响应标头
  • xhr object - 原始XHR实例
  • 错误 混合 - 错误信息,通常是错误实例(如果发生错误)
Node.js

请参阅 http.IncomingMessage

Error

它可能是一个错误或普通的 Object 实例,其中包含以下成员

  • 消息 string - 人类可读的错误消息描述
  • 状态 number - 内部错误代码或服务器HTTP响应状态
  • code number - 可选错误代码(仅限于node.js)
  • 堆栈 string - 可选的堆栈错误跟踪
  • 请求 对象 - 原始响应对象,以防自定义弹性错误发生。可选
  • 错误 错误 - 原始抛出的错误实例(仅限node.js)。可选
  • xhr XMLHttpRequest - XHR原生实例(仅限浏览器)
Built-in error codes
  • 1000 - 所有请求失败。没有服务器可用
  • 1001 - 无法更新发现服务器。空或无效的回复正文
  • 1002 - 缺少发现服务器。无法解析服务器
  • 1003 - 无法解析服务器。缺少数据
  • 1004 - 发现服务器响应无效或为空
  • 1005 - 重试过程中缺少服务器
  • 1006 - 内部状态错误(通常是由意外异常引起)
  • 1007 - 通过中间件注入错误

Events

弹性客户端内部支持内部状态事件分配器和公共接口的通知器

在使用拦截器模式以检测不同状态和数据更改时,这可能非常有用。 您可以拦截和更改订阅前/后请求钩子的任何请求和响应对象。 请注意,需要变异,您应该通过引用修改对象,不要丢失

// subscribe to every outgoing request before be dropped to the network
resilientClient.on('request:start', function handler(options, resilient) {
  // mutate the options, adding an aditional header
  options.headers['API-Token'] = 'awesome!'
  // unsubscribe example
  resilientClient.off('request:start', handler)
})
request:start

参数: options&lt; Object&gt; elastic&lt; Resilient&gt;

在创建请求之前触发

您可以即时拦截和修改请求选项,但必须将选项 object

request:outgoing

参数: options&lt; Object&gt; elastic&lt; Resilient&gt;

在通过网络发送HTTP请求之前每次都会触发

您可以即时拦截和修改请求选项,但必须将选项 object

request:incoming

参数: error&lt; Error&gt; response&lt; Object | http.IncomingMessage&gt; options&lt; Object&gt; 弹性&gt;

每次从服务器收到HTTP响应时,都会触发

request:finish

参数: error&lt; Error&gt; response&lt; Object | http.IncomingMessage&gt; elastic&lt; Resilient&gt;

请求完成后触发

您可以即时拦截和修改错误/响应,但必须将对象变为

request:retry

参数: options&lt; Object&gt; servers&lt; Servers&gt;

当请求执行重试尝试周期时,这意味着所有先前的请求失败

request:fallback

参数: options&lt; Object&gt; response&lt; Object&gt;

当给定服务器的任何请求(服务或发现)失败,并因此尝试执行下一个服务器后备时,Ff被触发

servers:refresh

参数: servers&lt; Array&gt; elastic&lt; Resilient&gt;

每次从发现服务器更新服务服务器列表时都会触发

servers:cache

参数: servers&lt; Array&gt; elastic&lt; Resilient&gt;

每次服务器缓存被更新时都会触发

discovery:refresh

参数: servers&lt; Array&gt; elastic&lt; Resilient&gt;

每次发现服务器都会刷新刷新服务器时触发

方法

弹性#发(路径,选项,回调)

使用给定的选项执行自定义请求。 建议使用通用接口进行多动词请求

elastic#get (路径,选项,回调)

返回客户端

使用可选的自定义选项

创建GET请求

elastic#post (路径,选项,回调)

返回客户端

使用可选的自定义选项创建POST请求 返回客户端

弹性#put (路径,选项,回调)

返回客户端

使用可选的自定义选项

创建PUT请求

弹性#删除(路径,选项,回调)

别名: del |返回客户端

使用可选的自定义选项

创建DELETE请求

弹性#补丁(路径,选项,回调)

返回客户端

使用可选的自定义选项

创建PATCH请求

弹性#头(路径,选项,回调)

返回客户端

使用可选的自定义选项

创建HEAD请求

弹性#options([type | options,options])

可选的每种类型的弹性选项的Getter / setter访问器。请参阅支持的选项

elastic#serviceOptions([选项])

服务级别配置选项的Getter / setter访问器

elastic#discoveryOptions([选项])

发现级配置选项的Getter / setter访问器

elastic#balancer([选项])

返回: object

平衡器级配置选项的Getter / Setter访问器

弹性#httpOptions(type)

返回: object

获取HTTP特定选项的映射

弹性#addFailStrategy(策略)

别名: failStrategy

添加自定义失败评估程序函数策略,以确定弹性应该如何处理请求失败或成功状态,如果需要,请相应地重试。

策略应返回一个 boolean 值,指示请求是否失败( true )或不( false

使用示例:

var resilient = require('resilient')

var client = resilient()

client.addFailStrategy(function limitReached(err, res) { return !err && +res.headers['x-ratelimit-remaining'] === 0 })

弹性#areServersUpdated()

返回: boolean

如果服务器是最新的,则返回 true 。否则 false

supports#serversURL([type =‘service’])

返回: array&lt; string&gt;

返回给定类型的服务器URL的数组。允许的类型是: service discovery

返回: Resilient 别名: resetStats

根据网络延迟和成功百分比和失败请求重置服务器统计分数

该分数是从客户端向每个服务器发送的请求总量的平均微积分。 该分数按顺序用于调度算法 以确定最佳可用服务器(在启用 balance 选项的情况下)

允许的类型是: service discovery

elastic#discoveryServers([ servers])

返回:服务器

Setter / Getter for discovery servers list

弹性#discoverServers([options,] cb)

返回:弹性

将回调传递给要求发现服务器的服务器的最新列表

传递参数到回调是:

  • 错误 对象 - 发生错误
  • 服务器 数组 - 使用当前服务服务器URL
  • string

弹性#latestServers([options,] cb)

返回: Resilient 别名: getUpdatedServers

将回调传递到服务器的最新列表,配置或不配置发现服务器

传递参数到回调是:

  • 错误 对象 - 发生错误
  • 服务器 数组 - 使用当前服务服务器URL
  • string

弹性#updateServers([options,] cb)

强制从发现服务器更新服务器列表(如果已定义) 可选地传递回调来处理结果

传递参数到回调是:

  • 错误 对象 - 发生错误
  • 服务器 数组 - 使用当前服务服务器URL
  • string

elastic#use(middleware)

注册一个新的中间件。有关详细信息,请参阅中间件文档示例

弹性#useHttpClient(fn)

使用自定义HTTP客户端作为代理,而不是嵌入的弹性本机HTTP客户端。

当您需要处理一些复杂的HTTP前/后挂钩逻辑并利用自定义HTTP客户端功能时,可用于在现有项目中为自定义框架或库定义use proxy。

如果定义了,通过Resilient客户端的所有传出请求都将被代理。

传递给客户端函数的参数:

  • 选项 对象 - 弹性HTTP 服务选项
  • 回调 function - 请求状态处理程序。预期的参数是: error response

注意:错误响应对象必须与当前界面兼容

elastic#restoreHttpClient()

恢复原生的弹性 HTTP客户端

弹性#mock(mockFn)

为所有传出请求定义模拟/假HTTP客户端错误/响应对象

resilient.mock(function (options, cb) {
  if (options.url === 'http://discovery.server.me') {
    // fake response
    cb(null, { status: 200, data: ['http://server.net'] })
  } else {
    // fake unavailable status
    cb(null, { status: 503 })
  }
})

另请参见用于自定义请求代理转发的 useHttpClient()方法,也可用于使用stubs / fakes进行测试

弹性#unmock()

禁用模拟/假模式

elastic#on(event,handler )

订阅活动请参阅支持的事件

elastic#off(event,handler )

取消订阅给定的事件及其处理程序。请参阅支持的事件

弹性#一次(事件,处理程序)

只需一次,就可以使用给定的处理程序订阅事件。 触发后,处理程序将被删除

请参阅支持的活动

弹性#cache.flush()

强制刷新服务器缓存

弹性#client()

返回:客户端别名: http

返回仅限客户端的接口。 有用的从公共使用提供封装 避免从公共API调用弹性特定的配置方法。

这是一个有限的API,用于为高级开发人员提供

elastic.VERSION

类型: string

当前的semov库版本

elastic.CLIENT_VERSION

类型: string

当前的semver HTTP客户端库版本

它在node.js和请求 http> lil-http 在浏览器中

elastic.defaults

键入: object

默认配置选项

elastic.Options(options)

创建新的选项存储

elastic.Client(弹性)

使用公共API创建一个新的弹性HTTP客户端

有用的是为弹性API提供封装,并仅暴露HTTP客户端(开发人员想要消费的公共接口)

elastic.request(options [,cb])

在node.js和请求) lil-js / http> lil-http )

常见问题

It's required to have discovery servers in my infraestructure in order to use Resilient?

绝对不会。在您的Resilient客户端中配置它们的情况下,才会使用发现服务器。 在这种情况下,Resilient将简单地使用静态服务服务器与您的后端

进行通信

Can I use Resilient as a simple HTTP client without balancing?

是的。如果您使用完整的URI模式执行请求,则Resilient会将其视为简单请求,而不应用任何内部逻辑:

var client = Resilient({
  service: {
    servers: ['http://server1.me', 'http://server2.me']
  }
})

// direct plain request (no balancing, no discovery, no fallback…) client.get('http//custom.server/hello', function (err, res) { // })

// resilient powered request (with balancing, fallback, discovery server, cache…) client.get('/hello', function (err, res) { // })

Can I use a custom HTTP client instead of the embedded one?

当然你可以这样做。在浏览器环境中,这是一个常见的前提,例如,您需要使用您在应用程序中使用的框架的自定义HTTP客户端,或者像zepto或jQuery这样的自定义库,它提供了一个简单的AJAX接口

您可以定义函数中间件作为代理模式,以通过Resilient客户端拦截和包装所有HTTP流量

var client = Resilient({})
// example using Zepto.js AJAX interface
client.useHttpClient(function httpProxy(options, cb) {
  options.success = function (data, status, xhr) {
    cb(null, { status: xhr.status, data: data, xhr: xhr })
  }
  options.error = function (xhr) {
    cb({ status: xhr.status, xhr: xhr })
  }
  $.ajax(options)
})

有关详细信息,请参阅 API方法文档

Can I use streams?

还没有有计划在将来的版本中支持它。

Can I use Resilient in production projects?

在web和node.js生产应用程序中都使用了弹性。

图书馆确实比较年轻,并将在未来版本中发展新功能(实际上需要全面的核心和逻辑重新设计),但是API的一致性并没有影响到次要版本。

How can I create custom middleware?

您可以看到中间件文档或查看示例

贡献

想要帮助?凉!将不胜感激:)

您必须为任何新功能或重构器添加新的测试用例, 始终遵循已经存在的相同设计/代码模式

开发

开发需要 node.js

克隆资源库

安装开发依赖关系

$ npm install

安装浏览器依赖关系

$ bower install

生成浏览器包源

$ make browser

运行测试(在node.js和headless浏览器中)

$ make test

在实际浏览器中运行测试

$ make test-browser

许可证

MIT ©Tomas Aparicio和贡献者




相关问题推荐