JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 294
  • Score
    100M100P100Q85784F
  • License MIT

extend WHATWG fetch wrapping it with middlewares

Package Exports

  • fetch-wrap

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (fetch-wrap) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

fetch-wrap

Build Status Code Climate Test Coverage NPM version NPM dependencies

extend WHATWG fetch API with middleware

  • transparent, your extended fetch mantains fetch API fetch(url, options)
  • recursive, extend fetch, extend extended fetch, ...
  • use over any fetch implementation you like (native fetch, fetch-ponyfill, fetch-polyfill, etc.)
  • pick from built-in middleware and/or write yours
  • unit tested and benchmarked against plain fetch
  • isomorphic

Install

npm install fetch-wrap --save

Usage

const fetchWrap = require('fetch-wrap');

// you can use native fetch(), or the implementation you prefer
let fetch = require('fetch-ponyfill')();

// extend fetch with a list of wrappers
fetch = fetchWrap(fetch, [
  function middleware1(url, options, innerFetch) {
    // this middleware does nothing
    return innerFetch(url, options);
  },
  middleware2,
  middleware3,
]);

// use your extended fetch
fetch('http://localhost:8080/file.json').then(result => console.log(result));

Built-in Middleware

There's some useful middleware in this package that you can optionally import see src/middleware.js for details, here's a full example:

var fetchWrap = require('fetch-wrap');
var middleware = require('fetch-wrap/middleware');
var fetch = fetchWrap(fetch, [
  // support options.params, replace tokens in url and adds query string params
  middleware.urlParams({
    host: 'localhost'
  }),
  // apply options based on url (supports wildcards)
  middleware.optionsByUrlPattern([
    {
      for: 'http://localhost*',
      options: {
        headers: {
          Authorization: 'Token 1234'
        },
        timeouts: {
          // will send log events at 2s and 5s with these levels
          2: 'warn',
          5: 'error' // 5sec timeout from localhost, error!
        }
      }
    }
  ]),
  // automatically serialize body to JSON if needed
  middleware.sendJson(),
  // automatically parse JSON (revives Dates), optionally send Accept header
  //   throws on http errors
  middleware.receiveJson()
  // logs events (start, success, fail, timeouts), defaults to console but supports custom .log handler
  middleware.logger()
]);

fetch('http://{host}:8080/test.json', {
  params: {
    utm_source: 'nodejs'
  }
}).then(result => console.log(result));

Write your own Middleware!

const fetchWrap = require('fetchWrap');
fetch = fetchWrap(fetch, [

  function(url, options, fetch) {
    // modify url or options
    return fetch(url.replace(/^(http:)?/, 'https:'), options);
  },

  function(url, options, fetch) {
    // add headers
    return fetch(url, fetchWrap.merge({}, options, {
      headers: {
        Authorization: 'Token 123456'
      }
    });
  }

  function(url, options, fetch) {
    // modify result
    return fetch(url, options).then(function(response) {
      if (!response.ok) {
        throw new Error(result.status + ' ' + result.statusText);
      }
      if (/application\/json/.test(result.headers.get('content-type'))) {
        return response.json();
      }
      return response.text();
    });
  }

  function(url, options, fetch) {
    // catch errors
    return fetch(url, options).catch(function(err) {
      console.error(err);
      throw err;
    });
  }

]);

// use your customized fetch!

fetch('http://somedomain.com/news.json').then(function(news) {
  // GET https://somedomain.com/news.json with Authorization header, and parsed to json
  console.log(news.items);
});

Testing

For unit testing, you can use the built-in testing middleware to mock or spy fetch calls.

var fetchWrap = require('fetch-wrap');
var middleware = require('fetch-wrap/middleware');
var spyLog = [];
var fetch = fetchWrap(fetch, [
  middleware.optionsByUrlPattern([
    {
      for: 'http://localhost*',
      options: {
        // mock every request to this url
        mock: { name: 'john' }
      }
    }
  ])
  middleware.testing({
    // optional spy function
    spy(url, options) {
      spyLog.push({ url: url, options: options })
    }
  })
]);

// it will fail if no `options.mock` is found, to prevent real requests during unit-testing
fetch('http://localhost:8080').then(function(result) {
  expect(spyLog[0].url).to.eql('http://localhost:8080');
  expect(result).to.eql({ name: 'john' });
})

For details on built-in middleware check src/middleware.js

Benchmark

node src/benchmark

compares fetch (fetch-ponyfill, not extended), with extended fetch (fetch-ponyfill extended with some of the built-in middleware).

Typically results show performance cost is neglectable, example:

fetch GET json x 435 ops/sec ±1.52% (80 runs sampled)
extended fetch GET json x 438 ops/sec ±1.24% (81 runs sampled)