Customising redux-api-middleware calls
Tags: react, redux, middleware, api
Published: 2019-10-31 10:08:01

---
title: Customising redux-api-middleware calls
published: true
description: Customise redux-api-middleware using values from the store
tags: react, redux, middleware, api
---

I've been using the [redux-api-middleware](https://github.com/agraboso/redux-api-middleware) for contacting a secure API and because of the need for an `Authorization` header to be sent with each request found that I was needing to use function values for most of my actions such as the following.
```json
{
    [RSAA]: {
        headers: state => {
            return {
                Authorization: state.authorizationToken
            }
        },
        endpoint: "/my/api/endpoint,
        method: "GET"
    }
}
```
The headers property will accept either an object, or a function which returns an object. In this case I was using the latter to retrieve the authorization token and adding it to each request. Continuing like this would mean each new request needed the same boilerplate to be repeated each time. To solve the problem I decided to use a custom redux middleware.

## Custom Middleware

Middleware is formulated as a pipeline of many middlewares, each passing the dispatched action on to the next middleware before the reducers handle it. If we create a custom middleware that gets to the actions before the redux-api-middleware gets a chance then we can manipulate the dispatched action and make the changes apply to all of our requests removing the need for all that repeated code.

One solution here would be to create a function that adds the `Authorization` header. This could look something like this

```javascript
const apiAuthorizationMiddleware = (store: any) => (next: any) => (action: any) => {
    // Pass to next middleware if not a redux-api-middleware action
    if (!action[RSAA]) {
        return next(action)
    }

    return {
        ...action,
        [RSAA]: {
            ...action[RSAA],
            headers: {
                ...action[RSAA].headers,
                Authorization: store.getState().authorizationToken
            }
        }
    }
}
```
But this would mean that you would always be adding that header. What about requests to different services? You don't want to be passing your "secure" API authorization token around all over the place. Instead what I'm going to do is replace the `RSAA` with a different value that will identify the requests I want to add the header to. This means my new action will look like this.
```json
{
    [MY_AUTHORIZED_REQUEST]: {
        endpoint: "/my/api/endpoint,
        method: "GET"
    }
}
```
Note how I've replaced `[RSAA]` with a new value. That value is what we're going to change our custom middleware to look for.

```javascript
import { RSAA } from 'redux-api-middleware'

export const MY_AUTHORIZED_REQUEST = "@@authorized_request"

export const apiAuthorizationMiddleware = (store: any) => (next: any) => (action: any) => {
    if (!action[MY_AUTHORIZED_REQUEST]) {
        return next(action)
    }

    const { [MY_AUTHORIZED_REQUEST]: request, ...newAction} = action
    
    const headers = request.headers ? {...request.headers} : {}
    const state = store.getState()
    headers["Authorization"] = state.authorizationToken

    request.headers = headers

    newAction[RSAA] = request
    return next(newAction)
}

export default MY_AUTHORIZED_REQUEST
```
Adding this middleware as well as the `redux-api-middleware` now means we can fetch `[RSAA]` requests without adding the authorization token header, and `[MY_AUTHORIZED_REQUEST]` requests with the authorization token header added from the value in the redux state.
This is just one example of what can be done with the middleware, you can change the request in any way you like, for example adding additional query string parameters, or changing the base url.

## Setting up the store

Applying the custom middleware is done by adding it in to the pipeline ahead of the `redux-api-middleware` function along with any other middleware you use.
```javascript
let createStoreWithMiddleware = applyMiddleware(apiAuthorizationMiddleware, apiMiddleware, routerMiddleware(history), thunkMiddleware)(createStore)
const store = createStoreWithMiddleware(reducer(history), initialState);
```