Skip to content

Instantly share code, notes, and snippets.

@benpickles
Created March 18, 2016 16:19
Show Gist options
  • Star 45 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • Save benpickles/b465db90ca11adc9ea00 to your computer and use it in GitHub Desktop.
Save benpickles/b465db90ca11adc9ea00 to your computer and use it in GitHub Desktop.
Inject an Authorization header into a redux-api-middleware request with a Redux middleware.
import { CALL_API } from 'redux-api-middleware'
export function fetchLocations() {
return {
[CALL_API]: {
endpoint: 'http://api.somesite.com/api/locations',
method: 'GET',
// Don't have to manually add the Authorization header to every request.
headers: { 'Content-Type': 'application/json' },
types: ['REQUEST', 'SUCCESS', 'FAILURE']
}
}
}
// ...Likely some other imports such as React etc.
import { createStore, applyMiddleware } from 'redux'
import { apiMiddleware } from 'redux-api-middleware'
// Our custom middleware.
import apiAuthInjector from './apiAuthInjector'
const store = createStore(
reducers,
applyMiddleware(
apiAuthInjector, // Put it somewhere before `apiMiddleware`.
apiMiddleware,
)
)
// ...the rest of your app setup.
import { CALL_API } from 'redux-api-middleware'
import ls from 'local-storage'
export default function() {
return function(next) {
return function(action) {
const callApi = action[CALL_API]
// Check if this action is a redux-api-middleware action.
if (callApi) {
// Inject the Authorization header from localStorage.
callApi.headers = Object.assign({}, callApi.headers, {
Authorization: ls.get('id_token') || '',
})
}
// Pass the FSA to the next action.
return next(action)
}
}
}
@jordan112
Copy link

how can i buy you a virtual beer? :)

@nickhsu
Copy link

nickhsu commented Apr 20, 2016

ES6 style function

export default store => next => action => {
  const callApi = action[CALL_API]

  // Check if this action is a redux-api-middleware action.
  if (callApi) {
    // Inject the Authorization header from localStorage.
    callApi.headers = Object.assign({}, callApi.headers, {
      Authorization: ls.get('id_token') || '',
    })
  }

  // Pass the FSA to the next action.
  return next(action)

}

@jordanmkoncz
Copy link

jordanmkoncz commented May 23, 2017

Thanks for this! I used this to make a few different changes to the CALL_API action.

Here's my full middleware in case it's helpful to anyone:

import { CALL_API } from 'redux-api-middleware';
import isNil from 'lodash/isNil';
import get from 'lodash/get';

export default store => next => action => {
  const callApi = action[CALL_API];

  // Check if this action is a redux-api-middleware action.
  if (callApi) {
    // Prepend API base URL to endpoint if it does not already contain a valid base URL.
    if (!/^((http|https|ftp):\/\/)/i.test(callApi.endpoint)) {
      callApi.endpoint = `127.0.0.1:8000${callApi.endpoint}`;
    }

    // Set headers to empty object if undefined.
    if (isNil(callApi.headers)) {
      callApi.headers = {};
    }

    // Set Content-Type to application/json if Content-Type does not already have a value.
    if (isNil(get(callApi.headers, 'Content-Type', null))) {
      callApi.headers['Content-Type'] = 'application/json';
    }
  }

  // Pass the FSA to the next action.
  return next(action);
};

@TheRobBrennan
Copy link

Dude! You are a lifesaver. Thanks so much - this was exactly what I needed to solve my problem

@vnallamhawk
Copy link

Hi Team,

Where are we actually setting the localstorage value for the authorization header?

@smerin
Copy link

smerin commented May 31, 2018

Any thoughts on how to get the token from redux state rather than local storage? I've been trying to use thunk's getState but can't get it working.

@thclark
Copy link

thclark commented Jun 4, 2018

@smerin hidden in the jungle of the redux docs explaining middleware it's noted that we still have access to the top level store

...It's still useful to have access to some store methods like getState(), so store stays available as the top-level argument.

That's actually part of a monkeypatching demo explaining how middleware is built up... but follow down and you see it's available in the end results too, so you can simply call store.getState() from within your custom middleware to get it out of your redux store instead of the local storage as demonstrated above.

@philihp
Copy link

philihp commented Oct 9, 2018

I think the last file was meant to be named apiAuthInjector.js, rather than authApiInjector.js

@ontimond
Copy link

ontimond commented Jul 28, 2020

Hi, i modified the apiAuthInjector method to be compatible with the new version of redux-api-middleware

import { isRSAA, RSAA } from 'redux-api-middleware'
import ls from 'local-storage'
import produce from "immer"

export function apiAuthInjector() {
    return function (next) {
        return function (action) {

            // Check if this action is a redux-api-middleware action.
            if (isRSAA(action)) {
                let call = action[RSAA];
                call.headers = produce(call.headers || {}, draftHeaders => {
                    draftHeaders.Authorization = ls('access_token') || '';
                });
            }

            // Pass the FSA to the next action.
            return next(action)
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment