Skip to content
📮 Minimalistic Fetch based HTTP client
JavaScript Shell
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.
.github Add CODEOWNERS Jul 26, 2017
assets Add logo Nov 20, 2017
build Create coverage directory before building (#67) Jul 27, 2017
docs Update dev deps (#66) Jul 6, 2017
lib Uppercase methods when calling fetch (#62) May 3, 2017
scripts 🔧 Update publish script. Jan 12, 2017
test Update dev deps (#66) Jul 6, 2017
.all-contributorsrc Add all-contributors (#44) Jan 10, 2017
.babelrc Create build process using webpack Nov 17, 2016
.bithoundrc Minor improvements (#27) Dec 2, 2016
.chimirc Add chimi to test docs (#68) Jul 26, 2017
.editorconfig Rework after middleware response/rejection object (#60) Mar 28, 2017
.eslintignore Add config properties to readme (#36) Jan 4, 2017
.eslintrc Minor improvements (#27) Dec 2, 2016
.gitignore Rework after middleware response/rejection object (#60) Mar 28, 2017
.npmignore 🔧 Update config files. Dec 15, 2016
LICENSE Add LICENSE, improve readme and fix code styling Nov 28, 2016
package.json Bump rollup from 0.41.6 to 0.58.2 (#112) Apr 28, 2018
yarn.lock Bump rollup from 0.41.6 to 0.58.2 (#112) Apr 28, 2018


Minimalistic HTTP client for the browser and Node. 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 dependencies Status devDependencies Status


  1. Install
  2. Basic Usage
  3. Trae API
  4. Request methods
  5. Config
  6. Defaults
  7. Middlewares
  8. Instances
  9. Response
  10. Data
  11. Headers
  12. Rejection
  13. Resources
  14. License
  15. Contributing
  16. Contributors
  17. TODO


$ npm install --save trae
$ yarn add trae

Basic Usage

A GET request to

trae.get('', { params: { q: 'foo' } })
  .then((response) => {
  .catch((err) => {

A POST request to'', {
  title  : 'My Post',
  content: 'My awesome post content...'
  .then(() => {
  .catch((err) => {

Check out more examples here.

⬆ back to top

Trae API

Request methods

trae.get(url[, config]);

trae.delete(url[, config]);

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

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

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

⬆ back to top


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:
  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:
  // 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:
  // 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:
  // Default: 'default'
  cache: 'only-if-cached'

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



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

  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:

  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({ ... }).


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


const baseUrl = trae.baseUrl();
console.log(baseUrl); // ''

trae.get('/baz'); // GET:


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


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.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); = 'bar'
  return res;

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

trae.after(fullfillMiddleware, rejectMiddleware);

Using the above after middleware is the same as doing:

  .then(fullfillMiddleware, rejectMiddleware);


Runs at the end regardless of the request result, it has access to the configuration object and the url that was used to made the request. Is not promise based. Functions provided to this method are run synchronously.

const finallyMiddleware = (config, url) => {
  console.log('The End');


⬆ back to top



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.

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


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

  // body of the response
  data: { ... },

  // status code of the response
  status: 200,

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

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

  // the config used to execute the request
  config: { ... },


Response body 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.

bodyType is not used on rejection, response body is read according to response.headers['Content-Type'].

In both cases it is passed to the after middleware as the data property.


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


On rejection an Error is passed to the rejection middleware with the same properties as the response object.

⬆ back to top



MIT License.


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!


Thanks goes to these wonderful people (emoji key):

Nicolas Del Valle

💻 📖 ⚠️ 💡 👀

Christian Gill

💻 📖 ⚠️ 💡 👀

Ignacio Anaya

💻 👀 🎨 🐛 💁

Fred Guest

💁 🐛



Gerardo Nardelli


⬆ back to top


  • Provide a build with no polyfill.
  • CHANGELOG. #48
  • Add logging and warnings to the dev build. #49
  • Improve examples and add more. trae-exampels repo.
  • Add a way to remove middlewares.
  • Add browser based tests.

⬆ back to top

You can’t perform that action at this time.