Giter Club home page Giter Club logo

flashheart's Introduction

flashheart


Flashheart


NPM downloads Build Status

A fully-featured Node.js REST client built for ease-of-use and resilience

flashheart is built on http-transport to provide everything you need to build HTTP-based services with confidence.

Installation

npm install --save flashheart

Usage

const flashheart = require('flashheart');

const client = flashheart.createClient({
  name: 'my_service',
  logger: console
});

const response = await client.get('http://echo.jsontest.com/key/value/');
console.log(response.body);
// {key: "value"}

Documentation

For more examples and API details, see API documentation

Test

npm test

To generate a test coverage report:

npm run coverage

flashheart's People

Contributors

cloud-hai-vo avatar davidc6 avatar dependabot[bot] avatar djmcdonald avatar greenkeeperio-bot avatar hjerling avatar jasonwilliams avatar jeanrauwers avatar mousius avatar niklasr avatar nspragg avatar robinjmurphy avatar subsidel avatar thom4parisot avatar usainbloot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flashheart's Issues

Missing ./core in v3.1.1

Hi,

I installed the v.3.1.1 and we have an issue in our release package, the current ./core is missing in our release

Will cause error with import

import { RequestOptions } from 'flashheart/dist/core/restClient';

Client request headers are overwritten by flashheart

We are trying to pass Client browser's signature (request headers) to our back-end application. As of now what we are observing is the flashheart is overriding the User-Agent header.
How can we disable flashheart to overwrite certain headers?

Confusing options on createClient

The option object passed on createClient should not contain request settings directly.
timeout and User-Agent can be passed on options.default so it's clear that request settings are being overwritten.

this.timeout = _.isUndefined(opts.timeout) ? DEFAULT_TIMEOUT : opts.timeout;

this.userAgent = _.isUndefined(opts.userAgent) ? util.format('%s/%s', package.name, package.version) : opts.userAgent;

hoek dependency

advisory

└─┬ [email protected]
  ├─┬ [email protected]
  │ └── [email protected] 
  ├─┬ [email protected]
  │ └─┬ [email protected]
  │   ├── [email protected]  deduped
  │   └─┬ [email protected]
  │     └── [email protected]  deduped
  └─┬ [email protected]
    ├─┬ [email protected]
    │ └── [email protected]  deduped
    └── [email protected]  deduped

reported on levee & request.

Wreck current version is 14.0.2, which depends on [email protected].

So this repo is waiting on levee & request, but updating wreck would resolve.

unexpected behaviour on 400 error

When a ~400 error condition is detected the response 'body' is not returned in the usual manner.

I honestly don't know if this is the correct approach for flashheart or not. However, it's not uncommon for an api to return information about an error in the request body. Because Error.prototype.toStack() method just dumps the stack, the only way to know that the information you're looking for is stored in a body property on err is to look through the source.

Can it be configured to retry on 400 errors?

My use case is that I want to retry until a 200 status code is received (this is because the 200 code depends on another data set turning from "pending" to "approved"). Is this possible with this library? It seems like this would be a straightforward feature to add, so I am curious.

Custom logging formats

It would be nice to change the logging format of Flashheart.

For data/log visualisers that leverage JSON logs like Kibana, having the upstream access log as a single message becomes hard to parse, i.e.

GET http://echo.jsontest.com/hello/world 200 10 ms

Libraries like Morgan allow for custom format functions, e.g.

morgan((tokens, req, res) => tokens)

Which would return the JSON object of all of the tokens that Morgan monitors.

Since Flashheart allows you to inject your own logger, it makes sense (to me at least) to be able to define your own formatter to return the right thing for the logger to consume.

This could also give users access to more information that's on the request and response options, I would like to be able to define something like

const format = (req, res) => ({ short: `${req.method} - ${res.statusCode}`, time: res.elapsedTime })

createClient({ format, logger })

And this could easily be done here with something like;

Client.prototype._log = function (res) {
  var debugMessage = util.format(res.request.method, res.request.href, res.statusCode, res.elapsedTime, 'ms');

  debug(debugMessage);

  if (this.logger) {
    var logMessage = this.format 
      ? this.format(res,request, res) 
      : debugMessage

    this.logger.info(logMessage);
  }
};

Assuming that you still want the debug message to be string only.

What do you guys think?

Cache Misses and Hits don't include feed name

Description
It's great that we can override the name of our client on a per-request basis.
This enables us to have a single-configured client which we can use for multiple feeds. However we do wish to monitor the cache-hits and misses of each individual feed, and it seems currently flashheart doesn't allow that.

Problem
When it comes to the cachingClient, the feedname isn't taken into account.
I've added a PR (attached) which fixes that, here is an example..

http.cache.misses
GET https://navigation.api.bbci.co.uk/api 200 147 ms
http.Orbit.requests
http.Orbit.responses.200
http.Orbit.response_time 147
http.Orbit.attempts 1
http.cache.misses
GET https://radio-nav-service.api.bbci.co.uk/radio-nav-service/json 200 414 ms
http.RadioNavService.requests
http.RadioNavService.responses.200
http.RadioNavService.response_time 414
http.RadioNavService.attempts 1
http.cache.hits
http.cache.hits

You can see that cache.hits and cache.misses don't include the feed name, so i can't tell here whether its RadioNavService or Orbit which is hitting the cache

Cannot get binary data - encoding option not available in v3 as it was in v2

In v2 we used to be able to pass in the encoding option to get requests to have request return the data back as a Buffer instead of a string. That option is not supported in v3. Instead the docs say to set the json request option to false:

If you need to call an API that returns plain text, XML, animated GIFs etc. then set the json flag to false in your request options.

However, this option isn't even implemented, and if it were implemented it still wouldn't work.

Adding:

if (opts && opts.encoding !== undefined) {
    req.use(httpTransport.setContextProperty({
        encoding: opts.encoding
    }, 'opts'));
}

to the get method in src/httpTransport/client.ts with the option encoding set to null causes body to be returned as a Buffer instead of a string - allowing support for binary data. However, it would be great to add support in a more generic fashion for additional request options.

Thanks.

Allow errors to be passed to callback without re-formatting

Allow a flag (simple is used by request-promise https://github.com/request/request-promise#api-in-detail which defaults to true) which prevents formatting errors with a new message, body, etc. when the status code family != 2xx.

Motivation

Currently we (BBC ID) use our own https://github.com/request/request wrapper, https://github.com/bbc/id-http-client.

We began constructing this before we were aware of Flashheart's existence, and we seem to slowly be bringing it up to feature parity with Flashheart due to product/resilience needs. We'd rather not duplicate these non-product specific features in BBC estate

Ideally we'd be able to instead wrap Flashheart to gain circuit breakers, retries, rate limiting and built-in-cache, and roll our own stats and logs as we see fit (for example for statsd we use datadoghq.com, and the statsd protocol wrapper dogstatsd).

Problem

Currently we're unable to wrap Flashheart due to the change in error format from standard request. We currently have the chain of request decoration, request -> bbc-http-client-node -> request-promise -> id-http-client, request-promise or id-http-client would be unable to interpret the reformatted errors passed via 'errorback'.

If these could be returned as normal, without filtering by statusCode etc, we could in theory consume Flashheart (request -> bbc-http-client-node -> flashheart -> request-promise -> id-http-client) while keeping the same API, with new errors thrown by Flashheart falling into request-promise' RequestError prototype.

Redis as the default external cache

Currently, clients have to configure external cache and pass it to flashheart. We could set Redis as the default external cache and allow clients to override this. Any thoughts / suggestions? Thanks.

Initialising with catbox-redis synchronously causes a race condition

Currently the client is created synchronously. In particular, the start function of the Catbox instance is passed noop rather than a callback. This has the potential to cause a race condition while the client attempts to connect to Redis when using catbox-redis.

My feeling is that the whole create client function should be async for consistency, but this obviously would be a breaking change and is generally unnecessary when using memory caches.

For this reason I propose to create a createClientAsync function and make that available to use separately. I'll raise a PR for you to review.

Migrate to TS

Migrate to Typescript. Version 3 must retain the existing functionality, with the additional features:

  1. Support configurable certs
  2. Support configurable HTTP clients
  3. Request collapsing

Retry if a non-5xx error code is received

We'd like to pass in an array of HTTP status codes (when the client is created) that might trigger a retry (non error codes). Would you guys be OK with this?

Happy to do the work myself.

Can you expose when a request is cached?

We want to be able to monitor when we make a cold call to an API, but not monitor cached calls. It's hard for us to know when a response is coming from a cache or whether it comes from the real thing (as this logic is buried within the API).

Are you able to expose some flag to say whether the response was cached or not? Or is this already possible and i don't know how to do it pings @nspragg

It would be nice if we could use the stats field, but we use cloudwatch and i don't know if the StatsD stuff works with that

Support with request-promise

I am trying to use this package with request-promise for requests that look more like this:

client.post(url, body).then(res => console.log(res));

I'm not able to get this working, but is there any recommended usage with Promises? Thank you.

Does/can getAsync return response in .then call?

Hey guys.

I'm using the getAsync function and i'm wondering if its possible to get the full response passed into the .then?

Here's my code:

this.restClient.getAsync(url, options)
   .then((body) => {
      ....
    })
   .catch((err) => {
      ....
   });

If I was using the callback based approach, I could do:

this.restClient.get(url, (err, body, res) => {
    ....
});

Which would give me access to the response object (including headers and status code). Is it possible to get a handle of this object using getAsync?

Thanks.

Cert configuration

Possible options:

  • Allow for a cert object/reference to be passed in the constructor.
  • Configure cert in a "transport" client (delegate) passed to the constructor.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.