为每个fetch()请求设置默认标题

59

使用fetch API,是否可以为每个请求设置默认标头?
我的想法是在localStorage中有JSON Web Token时设置Authorization标头。 我当前的解决方案是使用此函数设置标头:

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

在fetch请求中设置headers,代码如下:

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

但是肯定有更好的方法来做这件事。如果可以的话,我目前正在开发一个React/Redux/Express应用程序。


1
如果出于某种原因您不想使用现有的fetch包装器,编写一个添加授权头的包装器应该很简单。 - Davorin Ruševljan
5个回答

38

创建一个fetch包装函数可能会解决你的问题:

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));
}

如果您决定喜欢Axios或其他包,您还可以轻松地为应用程序中的所有调用切换请求客户端,并获得额外的好处。同时您还可以执行其他操作,例如检查options.body是否为对象并添加'Content-Type:application/json'标头。


10

Andri Möll 创建了一个 FetchDefaults.js 混合函数用于给 fetch 设置默认值:

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)
}

采用AGPL-3.0-only许可协议发布


9

你可以使用Axios代替fetch,并使用拦截器

const setAuthorization = (token) => {

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

}

Api是带有基本URL的axios对象

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

当您获得令牌后,只需调用函数setAuthorization。

来源:Axios README.md


2
你可以使用axios来设置授权头,然后使用普通的fetch请求,这样头部也会被设置为fetch请求。 - PhilWilliammee

4

您可以覆盖默认的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:


2

一种快速但不推荐的方法是重新定义默认的.fetch()函数:

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

代码未经测试和完成。如果您决定使用这个答案,请检查arguments.length,添加代码以保留现有的标头等。我只是提供了进一步探索的方向。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接