Skip to content

Instantly share code, notes, and snippets.

@benpickles
Created March 18, 2016 16:19
Show Gist options
  • Select an option

  • Save benpickles/b465db90ca11adc9ea00 to your computer and use it in GitHub Desktop.

Select an option

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
Copy Markdown

how can i buy you a virtual beer? :)

@nickhsu

nickhsu commented Apr 20, 2016

Copy link
Copy Markdown

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

jordanmkoncz commented May 23, 2017

Copy link
Copy Markdown

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
Copy Markdown

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

@vnallamhawk

Copy link
Copy Markdown

Hi Team,

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

@smerin

smerin commented May 31, 2018

Copy link
Copy Markdown

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

thclark commented Jun 4, 2018

Copy link
Copy Markdown

@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

philihp commented Oct 9, 2018

Copy link
Copy Markdown

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

@ontimond

ontimond commented Jul 28, 2020

Copy link
Copy Markdown

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