包详细信息

gofer

groupon159BSD-3-Clause5.3.0

A general purpose service client library

自述文件

nlm-github nlm-node nlm-version Build Status

gofer

A gofer, go-fer or gopher /ˈɡoʊfər/ is an employee who specializes in delivery of special items to their superior(s). The special items may be anything from a cup of coffee to a tailored suit or a car.

Wikipedia: Gofer

npm install --save gofer

A base class for HTTP clients. Usable in node, browsers, and react-native. The design is meant to enforce a certain level of consistency in how the clients are configured and instrumented.

Use in browsers might require a fetch polyfill.

If you used gofer 2.x before, you might want to read about all the changes in 3.x.

If you have some old gofer 3.x code that doesn't use classes and Promises, you can read the previous version of the 3.x docs.

API docsWalkthrough

Features

Options mappers

Option mappers are called in the order they are registered in and can potentially do anything they want. This can range from applying defaults over resolving custom api options to injecting access tokens.

Defaults merging

All configuration is just defaults which is one of the things making option mappers so powerful.

The precedence rules are (first wins):

  1. Explicit configuration in the API call
  2. Scoped overrides using client.with(options)
  3. Endpoint-level defaults
  4. Service-level defaults
  5. Global defaults

See the walkthrough below for how these are configured.

Copy with defaults / scoped overrides

You can create a copy of the API with hard defaults using with. This enables a nice pattern:

// We'll assume MyApiClient has an option mapper than knows how to
// properly send an accessToken, e.g. using an Authentication header
const client = new MyApiClient(config);

// After retrieving an access token
const authenticatedClient = client.with({ accessToken: 'some-token' });

// This one will now send an access token
// ~> `curl -H 'Authentication: Bearer some-token' \
//          http://api.example.com/personal/some-id`
authenticatedClient.protectedResource('some-id');

// This one was not changed, so it will not send one
// ~> `curl http://api.example.com/personal/some-id`
client.protectedResource('some-id');

This sounds great, but...

Why not use service specific client libraries?

Well, in a way that's what gofer encourages. The difference is that by basing all client libraries on this one, you gain consistency and unified configuration. Creating a client for a new service often takes just a couple of lines.

Why not use request?

request is a great swiss army knive for making API calls. This makes it an awesome first pick if you're looking for a quick way to talk to a wide variety of 3rd party services. But it's lacking in a few areas we care a lot about:

  • Good, predictable error handling
  • Flexible configuration
  • Instrumentation friendly

Walkthrough

Let's say we need a client for the Github API. The first step is to generate a Github client class:

const Gofer = require('gofer');

const { version, name } = require('./package.json')

class Github extends Gofer {
  constructor(config) {
    super(config, 'github', version, name);
  }
}

The name you choose here ("github") determines which section of the configuration it will accept. It's also part of the instrumentation as serviceName.

Let's define a simple endpoint to get the emojis from Github:

class Github extends Gofer {
  /* earlier stuff here */

  // Every instance of Github will get an `emojis` method, which has access
  // to `this.fetch()`  The `fetch` method works similar to WHATWG/fetch.
  emojis() {
    // fetch(uri: string, options: object?, callback: function?)
    return this.fetch('/emojis');
  }
}

To create an instance, we need to provide configuration. Configuration exists on three levels: global, per-service, and per-endpoint.

const config = {
  globalDefaults: {
    // these apply to all gofers
    connectTimeout: 30,
    timeout: 100,
  },
  github: {
    // these apply for every call made with Github
    clientId: '<VALID CLIENT ID HERE>',
    endpointDefaults: {
      // these only apply for calls to the emojis endpoint
      emojis: {
        connectTimeout: 100,
        timeout: 2000,
      },
    },
  },
};

To make our client a little nicer to use we'll add an option mapper that defaults baseUrl to the public Github API. The options we return will be passed on to fetch.

Github.prototype.addOptionMapper(opts => {
  // opts contains the already merged options, including global-, service-,
  // and endpoint-defaults. In our example opts.timeout will be 2000, etc.
  return {...opts,  baseUrl: 'https://api.github.com' };
});

Finally we can instantiate and make the call:

const github = new Github(config);

// The `fetch`-style:
github.emojis()
  .then(res => res.json())
  .then(emojiList => {
    console.log('Returned %d emojis', Object.keys(emojiList).length);
  })
  .catch(console.error);

// Using the added convenience of req.json()
github.emojis()
  .json()
  .then(emojiList => { /* ... same ... */ })
  .catch(console.error);

You can check examples/github.js for a richer example.

File Uploads

Gofer does not by default ship with support for multipart/form-data file uploads, but it is easy to add, using the form-data module, and an option mapper as shown in this multi-part mapper test.

更新日志

v5.3.0 (2024-02-12)

🚀 New Features

🐛 Bug Fixes

v5.2.4 (2022-05-23)

🐛 Bug Fixes

v5.2.3 (2022-04-07)

🏡 Internal

v5.2.2 (2022-02-28)

🏡 Internal

v5.2.1 (2022-02-28)

🐛 Bug Fixes

  • #128 fix: export type for registerEndpoints (@JimLiu)

v5.2.0 (2021-07-13)

🚀 New Features

v5.1.3 (2021-06-04)

🔼 Dependencies

  • 0741221 chore: bump ws from 7.4.4 to 7.4.6 (#123) - see: #123, 7
  • 19ae11c chore: bump hosted-git-info from 2.7.1 to 2.8.9 (#122) - see: #122

🏡 Internal

v5.1.2 (2021-03-29)

🐛 Bug Fixes

  • #121 fix: guard asyncStack capturing with captureAsyncStack option (@aaarichter)

v5.1.1 (2021-03-26)

🏡 Internal

v5.1.0 (2021-02-15)

🚀 New Features

v5.0.5 (2020-12-18)

🔼 Dependencies

5.0.4 - 2020-10-27

5.0.3 - 2020-10-27

  • docs: add warning to keepAlive options & update dependencies - @aaarichter #117
    • 4a1438a ♻️ chore: update dependencies
    • e764b95 🎨 style: fix eslint issues
    • 7fbedde 📝 docs: add warning to keepAlive options

5.0.2 - 2020-07-20

5.0.1 - 2020-03-18

5.0.0

Breaking Changes

drop support for Node < 10 needed for isomorphic uses of global URLSearchParams

See: 7223986

Commits

4.1.2

  • correct the API docs regarding qs - @dbushong #111
    • 500dd1f docs: correct the API docs regarding qs
    • 12c35c7 test: try to fix completionTimeout test race
    • 35f1b22 test: increase timeout for https test

4.1.1

  • Fix lgtm.com issues & package updates - @aaarichter #110
    • ba8ea4c chore: upgrade dependencies
    • 27caa09 fix: remove self-assigned variables
    • 97bf3e0 fix: body validating condition
    • 18d1a57 style: fix code inspection issues
    • 0c097cc style: fix lint error
    • 4d83c28 test: bump up timeout
    • 4bc3643 fix: set --allow-chrome-as-root to mochify setup

4.1.0

4.0.3

4.0.2

  • add property "defaults" to typedefs - @dbushong #107
    • 2219a1c fix: add property "defaults" to typedefs

4.0.1

4.0.0

Breaking Changes

Now requires a modern browser that can support basic ES6+ syntax

See: 739cf50

you no longer get a Bluebird-flavored Promise back when you call gofer functions in promise mode

See: f2bc735

Now requires Node 8.x and/or a browser with native URL and URLSearchParams support

See: bbe30c1

Commits

  • Modernize and Reduce package size - @dbushong #103
    • c9e684c chore: upgrade linting & node reqs
    • 56a3394 refactor: eslint --fix test
    • 739cf50 refactor: eslint --fix lib
    • 7f5a2ea test: fix test for new .eslintrc.json
    • f34c7eb test: fix tests for new mochify
    • f2bc735 refactor: use native Promises instead of bluebird
    • d869ea6 refactor: use lodash.* for remaining needs
    • 0e77ee5 test: use proper Buffer.from()
    • bbe30c1 refactor: use native URL & URLSearchParams

3.8.1

  • add missing verbs & make types match - @dbushong #102
    • 4c52721 fix: add missing verbs & make types match

3.8.0

  • add basic typescript type definitions - @dbushong #101
    • 36e7ea5 feat: add basic typescript type definitions
    • d6805f9 chore: update travis versions

3.7.9

3.7.8

3.7.7

3.7.6

3.7.5

3.7.4

  • Respect secureContext in options - @jkrems #95
    • f338444 fix: Respect secureContext in options

3.7.3

  • add note to README about multi-part uploads - @dbushong #94
    • 5b35197 docs: add note to README about multi-part uploads

3.7.2

3.7.1

  • modern docs & deps - @dbushong #92
    • 6cced2e docs: update docs to use modern JS
    • 7296fe7 docs: update examples to use modern JS
    • a60fe6c chore: run travis on more modern setup
    • f2c822a chore: update lint rules
    • 482213b chore: update deps to make npm audit clean

3.7.0

3.6.0

  • support fetch().stream().then() - @dbushong #90
    • 19b6c1e feat: support fetch().stream().then()
    • a9b6483 docs: wrap API docs @ 80 columns
    • 6c8e040 docs: .json(), .text(), etc.

3.5.8

  • don't set connect timeout for keepalive - @dbushong #86
    • cd57ced fix: don't set connect timeout for keepalive

3.5.7

  • clear completionTimer on response completion - @dbushong #84
    • 368d061 fix: clear completionTimer on response completion

3.5.6

  • use proper timeout to fix keepAlive - @dbushong #83
    • 7eb902f fix: use proper timeout to fix keepAlive

3.5.5

  • Ignore searchDomain for localhost and IP - @jkrems #80
    • 8cfb230 fix: Ignore searchDomain for localhost and IP

3.5.4

3.5.3

  • Fix header option leak - @jkrems #78
    • 4168096 test: Remove fixed certificates
    • 35a22df test: Use smaller reddit endpoint
    • c6a2397 fix: Prevent mutation of defaults
    • 485414a test: Verify that headers do not leak into defaults

3.5.2

  • Fix link to breaking changes doc - @jkrems #77
    • eb790cc docs: Fix link to breaking changes doc
    • 0d9759a chore: Modernize travis config
    • ea684dd test: Compare to proper base timing
    • fedc713 chore: Ignore package-lock.json

3.5.1

3.5.0

  • Port better timeout handling from 2.x - @jkrems #73
    • cdf0f37 feat: Port better timeout handling from 2.x

3.4.0

  • Support searchDomain option - @jkrems #69
    • 64396ad feat: Support searchDomain option

3.3.0

3.2.2

  • Add missing inheritance in example (3.x) - @jkrems #66
    • 724f08a docs: Add missing inheritance in example

3.2.1

3.2.0

  • Pass meta data into native methods - @jkrems #62
    • 109f6d1 feat: Pass meta data into native methods
    • 44ff043 refactor: Remove util dependency

3.1.1

3.1.0

  • Echo back the url in res.url - @jkrems #60
    • bbb0e6d feat: Echo back the url in res.url

3.0.1

3.0.0

  • 547db3b feat: Initial version of fetch
  • 57a04a4 test: Verify error.body
  • b3d86ad style: Use _.assign over O.assign
  • 1e6e79c refactor: Use bluebird instead of native
  • 15f0c70 refactor: Simplify agent options
  • f76b59a refactor: Remove random _property
  • a639184 feat: Add base class
  • 564886e fix: Working sub-classing
  • ca4dbf6 docs: Port README
  • 952ac4d docs: Add fetch-style example
  • cf0e5ef docs: Mention fetch over request
  • 196eef9 docs: baseUrl is now an option
  • 04ed5ba feat: Add legacy callback mode
  • 28b5a6a feat: Add callback support for Gofer
  • 91fe8d8 style: Use explicit lodash imports
  • 6a5e5b8 feat: Multi-level config handling
  • 69b5ccf feat: Expose Gofer as exports.default
  • 01e46bc docs: Add links to the exports
  • ec6b138 feat: Very basic browser support
  • 8e06e77 refactor: Remove http(s) from browser build
  • b2f3553 feat: Basics work in react-native
  • 05f88e8 test: Partially working test setup in phantom
  • c41e60a test: Run first actual browser test
  • fce491d test: Run the whole test suite in phantom
  • fd542fa feat: Support status code errors in browsers
  • 4e97ac2 doc: Update manual browser test instructions
  • 1e22002 test: Verify options.pathParams support
  • 7ecd8bc test: Legacy-compatible endpoints are possible
  • c26613c test: Verify response body stream
  • 71e8fe4 feat: Consistent header support for client-side
  • 6d55edb feat: Send body as string or buffer
  • cb1afeb test: Add missing body & qs tests
  • e7c4033 feat: options.auth support
  • 47c6121 test: options.headers test
  • 79fd337 feat: options.timeout
  • 5a42b47 feat: options.connectTimeout
  • 8c84f46 fix: Verify path params - see: #50
  • 4ed4471 test: Stream request body
  • fda4930 feat: https url support
  • bc217a0 feat: Use per-service http agent
  • c1ed538 feat: Support form-data as an option mapper
  • 054f9e6 doc: Port old API docs
  • 33ddfcb docs: Add example github API client
  • 3d5efa7 style: Remove invalid TODO
  • 8a9fe01 feat: Expose method and url on status code error
  • ce3bde4 chore: Add nlm beta channel