📮 Minimalistic Fetch based HTTP client for the browser
JavaScript Shell

README.md

trae

Minimalistic HTTP client for the browser. Based on Fetch API, allows trae to be future-proofing, to have a clean implementation and support streaming among other goodies.

Codeship Status for Huemul/trae Coverage Status bitHound Overall Score bitHound Dependencies bitHound Dev Dependencies bitHound Code All Contributors

Content

  1. Install
  2. Basic Usage
  3. Trae API
    1. Request methods
    2. Config
    3. Defaults
    4. Middlewares
    5. Instances
  4. Response
  5. License
  6. Contributing
  7. Contributors

Install

$ npm install --save trae
$ yarn add trae

Basic Usage

A GET request to https://www.google.com.ar/search?q=foo:

trae.get('https://www.google.com.ar/search', { params: { q: 'foo' } })
  .then((response) => {
    console.log(response);
  })
  .catch((err) => {
    console.error(err);
  });

A POST request to https://www.foo.com/api/posts:

trae.post('https://www.foo.com/api/posts', {
  title  : 'My Post',
  content: 'My awesome post content...'
})
  .then(() => {
    console.log('Success!!!');
  })
  .catch((err) => {
    console.error(err);
  });

⬆ back to top

Trae API

Request methods

trae.get(url[, config]);

trae.delete(url[, config]);

trae.head(url[, config]);

trae.post(url[, body[, config]]);

trae.put(url[, body[, config]]);

trae.patch(url[, body[, config]]);

⬆ back to top

Config

The configuration object can be used in all request methods, the following attributes are available:

{
  // Absolute or relative url of the request
  url: '/foo/bar',

  // The URL parameters to be sent with the request
  params: {
    id: 123
  },

  // Represents the body of the response, allowing you to declare what its content type is and how it should be handled.
  // Available readers are `arrayBuffer`, `blob`, `formData`, `json`, `text` and `raw`. The last one returns the response body without being     
  // parsed. `raw` is used for streaming the response body among other things.
  // @link: https://developer.mozilla.org/en-US/docs/Web/API/Body
  bodyType: 'json',

  // The Headers object associated with the request
  headers: {
    'Content-Type': 'application/json' // Default header for methods with body (patch, post & put)
    'X-My-Custom-Header': 'foo-bar'
  },

  // The mode of the request. Available values are: `same-origin`, `no-cors`, `cors` and `navigate`
  // @link: https://developer.mozilla.org/en-US/docs/Web/API/Request/mode
  // Default: 'cors'
  mode: 'same-origin',

  // Indicates whether the user agent should send cookies from the other domain in the case of cross-origin requests.
  // @link: https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials
  // Default: 'omit'
  credentials: 'same-origin',

  // The cache mode of the request. Available values are:
  // `default`, `no-store`, `reload`, `no-cache`, `force-cache` and `only-if-cached`
  // @link: https://developer.mozilla.org/en-US/docs/Web/API/Request/cache
  // Default: 'default'
  cache: 'only-if-cached'
}

More information about Request properties can be found on this MDN article.

Defaults

trae.defaults([config])

Sets the default configuration to use on every requests. This is merged with the existing configuration.

trae.defaults({
  mode       : 'no-cors',
  credentials: 'same-origin'
});

When called with no params acts as a getter, returning the defined defaults.

const config = trae.defaults();

It is possible to set default configuration for specific methods passing an object with the method as key:

trae.defaults({
  post: {
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    }
  }
});

Request configuration precedence

The configuration for a request will be merged following this precedence rules, each level overrides the followings:

  1. Request params config.
  2. Method config set with trae.defaults({ [method]: { ... } }).
  3. Trae config set with trae.defaults({ ... }).

trae.baseUrl([url])

Shorthand for trae.defaults({baseUrl: url}). Also returns the baseUrl when no params are passed.

trae.baseUrl('https://www.foo.com');

const baseUrl = trae.baseUrl();
console.log(baseUrl); // 'https://www.foo.com'

trae.get('/baz'); // GET: https://www.foo.com/baz

Middlewares

trae api provides three middleware methods, before, after and finally.

trae.before([middleware])

Runs before the request is made and it has access to the configuration object, it is run in a promise chain, so it should always return the configuration object.

const beforeMiddleware = (config) => {
  config.headers['X-ACCESSS-TOKEN'] = getUserToken();
  return config;
}

trae.before(beforeMiddleware);

trae.after(fullfill[, reject])

Runs after the request is made, it chains the provided fullfill and reject methods together to the then method from fetch response. When no fulfill callback is provided, the identity function is used. When no reject callback is provided, a rejected promise is returned, to be handled down the chain.

const fullfillMiddleware = (res) => {
  console.log(res);
  res.data.foo = 'bar'
  return res;
};

const rejectMiddleware = (err) => {
  console.error(err);
  err.foo = 'bar';
  return Promise.reject(err);
};

trae.after(fullfillMiddleware, rejectMiddleware);

Using the above after middleware is the same as doing:

trae.get('/api/posts')
  .then(fullfillMiddleware, rejectMiddleware);

trae.finally([middleware])

Runs at the end regardless of the request result. Is not promise based. Functions provided to this method are run synchronously.

const finallyMiddleware = () => {
  console.log('The End');
  makeTheSpinnerStop();
};

trae.finally(finallyMiddleware);

⬆ back to top

Instances

trae.create([config])

Creates an instance of Trae with its own defaults and middlewares. The API documentation applies for instances as well.

const api = trae.create({baseUrl: '/api'})

api.get('/posts') // GET: /api/posts

The created method inherits all the defaults and middlewares from its creator.

trae.baseUrl('/api')
const api = trae.create()

api.get('/posts') // GET: /api/posts

api.defaults({ mode: 'no-cors' })

const apiFoo = api.create()

apiFoo.defaults() // { mode: 'no-cors', ... }

⬆ back to top

Response

The request methods return a promise that resolves to this object:

{
  // the response that came from the server
  data: { ... },

  // status code of the response
  status: 200,

  // status message of the response
  statusText: 'OK',

  // headers of the response
  headers: { ... },
}

data

data is read using response.json() when response.headers['Content-Type'] contains application/json and will be an object, otherwise it is read using response.text() and will result in a string. If you need to use another reader , it can be specified by setting the bodyType config property.

headers

headers is an instance of Headers, it has methods handlers like append, get, getAll, has, set.

⬆ back to top

License

MIT License

Contributing

Create an issue to report bugs or give suggestions on how to improve this project.

If you want to submit a PR and do not know where to start or what to add check out the project page to find out what we are working on, and what to contribute next.

This project follows the all-contributors specification. Contributions of any kind welcome!

Contributors

Thanks goes to these wonderful people (emoji key):


Nicolas Del Valle

💻 📖 ⚠️ 💡 👀

Christian Gill

💻 📖 ⚠️ 💡 👀

Ignacio Anaya

💻 👀 🎨 🐛 💁

Fred Guest

💁 🐛

Joni

🎨

Gerardo Nardelli

📖

⬆ back to top