58

Is it possible, using the fetch API, to set default headers for every single request?
What I want to do is set an Authorization header whenever there is a json web token in the localStorage. My current solution is to set the headers with this function:

export default function setHeaders(headers) {
    if(localStorage.jwt) {
        return {
            ...headers,
            'Authorization': `Bearer ${localStorage.jwt}`
        }
    } else {
        return headers;
    }
}

Setting the headers in a fetch request would then look like this:

return fetch('/someurl', {
        method: 'post',
        body: JSON.stringify(data),
        headers: setHeaders({
            'Content-Type': 'application/json'
        })
    })

But there has to be a better way to do this. I'm currently developing a React/Redux/Express app if that is of any help.

eRodY
  • 635
  • 1
  • 6
  • 10
  • 1
    If for some reason you do not want to use existing wrappers around fetch, writing one to add authorization header should be straight forward. – Davorin Ruševljan Jun 29 '17 at 09:54

5 Answers5

38

Creating a fetch wrapper could solve your problem:

function updateOptions(options) {
  const update = { ...options };
  if (localStorage.jwt) {
    update.headers = {
      ...update.headers,
      Authorization: `Bearer ${localStorage.jwt}`,
    };
  }
  return update;
}

export default function fetcher(url, options) {
  return fetch(url, updateOptions(options));
}

You also get the added benefit of being able to switch your request client easily for all the calls in your application if you decide you like Axios or other package better. And you can do other things like check if options.body is an object and add the 'Content-Type: application/json header.

underblob
  • 946
  • 9
  • 10
10

You could use Axios instead of fetch, with Interceptors

const setAuthorization = (token) => {

  api.interceptors.request.use((config) => {
    config.headers.Authorization = 'Bearer ' + token;
    return config;
  });

}

Where Api is an axios Object with a base URL

const api= axios.create({
  baseURL: 'http://exemple.com'
});

And when you get your token, u just have to call the function setAuthorization.

Source: Axios README.md

Pierre C.
  • 1,591
  • 2
  • 16
  • 29
  • 2
    You can use axios to set your authorization headers and then use normal fetch request and the headers will be set for the fetch request as well. – PhilWilliammee Oct 04 '20 at 12:56
10

Andri Möll created a FetchDefaults.js mixin for fetch that sets fetch defaults:

var Url = require("url")
var assign = require("oolong").assign
var merge = require("oolong").merge
var PARSE_QUERY = false
var PROTOCOL_RELATIVE = true // Enable //example.com/models to mimic browsers.

exports = module.exports = function(fetch, rootUrl, defaults) {
  if (typeof rootUrl === "string") rootUrl = parseUrl(rootUrl)
  else defaults = rootUrl, rootUrl = null
  return assign(exports.fetch.bind(null, fetch, rootUrl, defaults), fetch)
}

exports.fetch = function(fetch, rootUrl, defaults, url, opts) {
  if (rootUrl != null) url = rootUrl.resolve(url)
  if (typeof defaults === "function") defaults = defaults(url, opts)
  return fetch(url, opts == null ? defaults : merge({}, defaults, opts))
}

function parseUrl(url) {
  return Url.parse(url, PARSE_QUERY, PROTOCOL_RELATIVE)
}

Distributed under AGPL-3.0-only license

Nantaphop
  • 570
  • 2
  • 13
3

You can override default fetch api:

var originalFetch = window.fetch;
window.fetch = function (input, init) {
    if (!init) {
        init = {};
    }
    if (!init.headers) {
        init.headers = new Headers();
    }

    // init.headers could be: 
    //   `A Headers object, an object literal, 
    //    or an array of two-item arrays to set request’s headers.`
    if (init.headers instanceof Headers) {
        init.headers.append('MyHeader', 'Value');
    } else if (init.headers instanceof Array) {
        init.headers.push(['MyHeader', 'Value']);
    } else {
        // object ?
        init.headers['MyHeader'] = 'Value';
    }
    return originalFetch(input, init);
};

References:

iuridiniz
  • 2,213
  • 24
  • 26
2

A quick and unrecommended hack is to redefine the default .fetch() function:

const oldFetch = window.fetch;
window.fetch = function() {
    arguments[1].headers = { 'blahblah' : 'blabla' };
    return oldFetch.apply(window, arguments);
}

Code is untested and unfinished. If you decide to use this answer, check arguments.length, add code to preserve existing headers, etc. etc. I'm just providing the direction for further exploration.

Alex from Jitbit
  • 53,710
  • 19
  • 160
  • 149