2024 answer
I would not advise you to override the global fetch API, you could run into issues if other libs or services depend on fetch.
Making a fetch wrapper is the way to go.
In the following I'll assume that we want to preserve all fetch API behaviours.
First step: create a helper to merge the headers
Since the headers of the fetch API can be passed either as:
- an object
- an entries array (eg
[['key1', 'val1'], ['key2', 'val2']]
)
- an Headers instance
We will need a mergeHeaders
helper.
I'll pass on the details but this is a working implementation:
function mergeHeaders (...headerInits) {
let result = {}
headerInits.forEach((init) => {
new Headers(init).forEach((value, key) => {
if (value === 'null' || value === 'undefined') {
// same as object spread: undefined overrides the current value
// 'null' and 'undefined' got stringified in the process and are not valid headers values
// therefore in this case we can remove the header
delete res[key]
} else {
// add the header
res[key] = value
}
})
})
return result
}
Second step: create the new fetcher
we can now proceed to implement a basic fetcher
function fetcher(input, options) {
// your headers
const defaultHeaders = { Authorization: localStorage.getItem('auth-header') }
// merge them with the headers of the options
const headers = mergeHeaders(defaultHeaders, options.headers)
// add the headers to the options
return fetch(input, { ...options, headers })
}
Third step: fix the autocomplete
If you don't use typescript you'll need to add a bit of jsdocs
jsdocs are type annotations that make use of the typescript lsp under the hood.
They will enable autocomplete
/**
* @type {typeof fetch}
*/
function fetcher(input, options) {
// your headers
const defaultHeaders = { Authorization: localStorage.getItem('auth-header') }
// merge them with the headers of the options
const headers = mergeHeaders(defaultHeaders, options.headers)
// add the headers to the options
return fetch(input, { ...options, headers })
}
Here we go, we have a fetcher with default headers!
If your use case starts becoming a bit more complex, consider using a library.
I recently published my fetch API configuration library, called up-fetch
Here is a quick example using up-fetch
const fetcher = up(fetch, () => ({
headers: { Authorization: localStorage.getItem('auth-header') }
}))
This achieves basically the same thing with a few differences: the response is automatically parsed, and an error is thrown if response.ok
is false
.
There are many more features like params as objects, baseUrl config, validation adapters, interceptors...
Hope that helps