Skip to content

Latest commit

 

History

History
293 lines (211 loc) · 7.01 KB

README.md

File metadata and controls

293 lines (211 loc) · 7.01 KB

Papi

This is a library for building HTTP API clients.

Documentation

papi.Client([options])

Initialize a new client.

Your client should extend the Papi Client class and call super(options) with the appropriate options.

Options

  • baseUrl (string): base URL, should not include trailing slash
  • headers (Object<string, string>, optional): defaults headers to include in every request
  • type (string, optional, supports: form, json, text): default request body encoding type
  • encoders (Object<string, Function>, optional): an object that maps a mime type to a function. The function should accept an object and return a Buffer.
  • decoders (Object<string, Function>, optional): an object that maps a mime type to a function. The function should accept a Buffer or string (must support both) and return an object.
  • tags (string[], optional): tags included in _log calls
  • socketPath (string, optional): unix socket path (baseUrl is still required)
  • timeout (number, optional): default number of milliseconds before request is aborted

Advanced options

  • agent (http.Agent|https.Agent, optionals): if not set uses the global agent
  • tls options: ca, cert, ciphers, clientCertEngine, crl, dhparam, ecdhCurve, honorCipherOrder, key, passphrase, pfx, rejectUnauthorized, secureOptions, secureProtocol, servername, and sessionIdContext (see Node.js docs for details)

Usage

const papi = require('papi');

class GitHub extends papi.Client {
  constructor(opts) {
    opts = opts || {};
    opts.baseUrl = 'https://api.github.com';
    opts.header = { accept: 'application/vnd.github.v3+json' };
    opts.timeout = 15 * 1000;

    super(opts);
  }
}

client._request(request, [middleware...])

Make an HTTP request.

Your client should use this or the shortcut methods listed below to execute HTTP requests in your client methods.

Arguments

  • request (Object): request options
  • middlware (Function<request, next>, optional): middleware functions that can mutate request.err or request.res. Call next without arguments to continue execution, next(err) to break with an error, or next(false, value) to return immediately.

Request

  • path (string): request path, can include variable segments defined by curly braces (ex: /user/{id})
  • method (string): request method
  • headers (Object<string, string>, optional): request headers
  • params (Object<string, string>, optional): sets variables in request path
  • query (Object<string, string|string[]>, optional): query parameters
  • body (Object|Buffer|Readable, optional): request body
  • type (string, optional, supports: form, json, text): request body encoding type
  • ctx (EventEmitter, optional): emit cancel to abort request
  • timeout (number, optional): number of milliseconds before request is aborted
  • tags (string[], optional): tags included in _log calls

There are also _get, _head, _post, _put, _delete, _patch, and _options shortcuts with the same method signature as _request.

Usage

class GitHub extends papi.Client {
  constructor() {
    // see example constructor above
  }

  async gists(username) {
    const opts = {
      path: '/users/{username}/gists',
      params: { username: username },
    };

    const res = await this._get(opts);
    return res.body;
  }
}

Result

[ { url: 'https://api.github.com/gists/9458207',
...

client._log(tags, [data])

Emit log events.

Arguments

  • tags (string[]): tags associated with event
  • data (optional): remaining arguments

Usage

client.on('log', function(tags) {
  console.log({
    tags: tags,
    data: Array.prototype.slice.call(arguments, 1),
  });
});;

client._log(['github', 'gist'], 'silas');

Result

{ data: [ 'silas' ], tags: [ 'debug', 'github', 'gist' ] }

client._ext(event, callback)

Register an extension function.

Arguments

  • event (string): event name
  • callback (Function): function to execute at a specified point during the request

Usage

client._ext('onRequest', (request, next) => {
  console.log('request', request.opts.method + ' ' + request.opts.path);

  request.start = new Date();

  next();
});

client._ext('onResponse', (request, next) => {
  const duration = new Date() - request.start;
  const statusCode = request.res ? request.res.statusCode : 'none';

  console.log('response', request.opts.method, request.opts.path, statusCode, duration + 'ms');

  next();
});

Result

request GET /users/{username}/gists
response GET /users/{username}/gists 200 1141ms

client._plugin(plugin, options)

Register a plugin.

Arguments

  • plugin (Object): plugin module
  • options (Object, optional): plugin options

Usage

client._plugin(require('papi-retry'));

papi.request(request, [callback...])

Shortcuts for making one-off requests.

See client request for full options list, with the exception that path is replaced with url.

Request

  • url (string): request url (ex: http://example.org/)

There are also get, head, post, put, delete (del), patch, and options shortcuts with the same method signature as request.

Usage

async function show() {
  const res = await papi.get('https://api.github.com/users/silas/gists');

  res.body.forEach(gist => console.log(gist.url));
}

Example

const papi = require('papi');

/**
 * GitHub API client
 */
class GitHub extends papi.Client {
  constructor(opts) {
    opts = opts || {};

    if (!opts.baseUrl) {
      opts.baseUrl = 'https://api.github.com';
    }
    if (!opts.headers) {
      opts.headers = {};
    }
    if (!opts.headers.accept) {
      opts.headers.accept = 'application/vnd.github.v3+json';
    }
    if (!opts.headers['user-agent']) {
      opts.headers['user-agent'] = 'PapiGitHub/0.1.0';
    }
    if (opts.tags) {
      opts.tags = ['github'].concat(opts.tags);
    } else {
      opts.tags = ['github'];
    }
    if (!opts.timeout) {
      opts.timeout = 60 * 1000;
    }

    super(opts);

    if (opts.debug) {
      this.on('log', console.log);
    }
  }

  /**
   * Get user gists
   */
  async gists(username) {
    const opts = {
      path: '/users/{username}/gists',
      params: { username: username },
    };

    const res = await this._get(opts);
    return res.body;
  }
}

// Print gists for user `silas`
async function main() {
  const github = new GitHub({ debug: true });

  const gists = await github.gists('silas');

  console.log('----');

  gists.forEach(function(gist) {
    if (gist.description) console.log(gist.description);
  });
}

if (require.main === module) {
  main();
} else {
  module.exports = GitHub;
}

License

This work is licensed under the MIT License (see the LICENSE file).