fetch() injecting a query variable/header value to every call

Viewed 1378

Right now, in my React-Native app I have the following:

fetch('http://localhost/SOMETHING', { 
    method: 'GET', 
    headers: { 
        'Content-Type': 'application/json', 
        'Authorization': 'Bearer '+this.state.authtoken 
    } 
})

Goal: Have my API know what UID is making the call. I know this should be in authtoken but different users can have the same authtoken.

My initial thought is to add a ?uid=${UID} to the end of every url. However, I have GET, POST, PATCHs, with their own set of queries

Another thought would be add a header value with the UID data.

Regardless of what I choose, it would be awesome to be able to add this value to every FETCH without having to do much else work.

Is this something that is possible? Open to suggestions on what you would do.

3 Answers

If You can then best would be to switch to Axios (https://github.com/axios/axios) - it's much easier to do that there.

But if You need to use fetch then https://github.com/werk85/fetch-intercept is your solution.

Example code

fetchIntercept.register({
  request: (url, config) => {

   config.headers = {
     "X-Custom-Header": true,
      ...config.headers
   };

    return [url, config];
  }
});

Not sure if you're willing to step away from fetch, but we use apisauce.

import { create } from 'apisauce';

const api = create({
  baseURL: 'http://localhost',
  headers: { 'Accept': 'application/json' },
});

api.addRequestTransform(request => {
  if (accessToken) {
    request.headers['Authorization'] = `bearer ${accessToken}`;
  }
});

api.get('/SOMETHING');

edit

If you want to keep it close to fetch, you could make a helper function.

let authToken = null;

export const setAuthToken = token => {
  authToken = token;
};

export const fetch = (url, options) => {
  if (!options) {
    options = {};
  }

  if (!options.headers) {
    options.headers = {};
  }

  if (authToken) {
    options.headers['Authorization'] = `Bearer ${authToken}`;
  }

  return fetch(url, options);
};

You will probably only use the setAuthToken function once.

import { setAuthToken } from '../api';

// e.g. after login
setAuthToken('token');

Then where you would normally use fetch:

import { fetch } from '../api';

fetch('http://localhost/SOMETHING');

I would not consider creating a onetime helper function and an extra import statement for each fetch a lot of "extra work".

You can build a wrapper function for fetching with uid

function fetchWithUid(baseUrl, uid, authtoken, options) {
    const { method, headers, body, ...rest } = options;
    const fetchOptions = {
        headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer ' + authtoken,
            ...headers,
        },
        method,
        ...rest,
    };

    if (body) {
        fetchOptions.body = JSON.stringify(body);
    }

    return fetch(`${baseUrl}?uid=${uid}`, fetchOptions);
}

Use the fetchWithUid function like this, the fetchOptions just mimic the original fetch function's option.

const fetchOptions = {
    method: 'POST',
    body: {
        hello: 'world',
    },
};

fetchWithUid('http://localhost/SOMETHING', 123, 'abcd', fetchOptions);
Related