My use case is:
- User requests asset from our API which fails because of JWT expiring (passed as an httpOnly cookie) - API returns a 401 status code.
- We go and authenticate them (without the user doing anything) again using a refresh_token to retrieve a new JWT with a request from our client to auth0.
- We send that new JWT to our API to be set as an httpOnly cookie to replace the expired one.
- We then want to retry the original request the user made to the API in step 1.
I'm trying to use Observables within my Redux app with redux-observable. If you can think of another way of making the above user flow work I would be happy to hear how.
NB. Im using rxjs V5
export const fetchAssetListEpic = (action$, store) => {
return action$.ofType('FETCH_ASSET_LIST')
.switchMap( action => {
const options = {
crossDomain: true,
withCredentials: true,
url: uriGenerator('assetList', action.payload)
};
return ajax(options);
})
.map(fetchAssetListSuccess)
.retryWhen(handleError)
.catch(redirectToSignIn);
};
function handleError(err) {
return (err.status === 401) ?
/* Authenticate here [Step 2] */
/* Send new JWT to API [Step 3] */
/* If successful make original request again [Step 4] */
:
Observable.throw(err);
}
function redirectToSignIn() {
/*I will redirect here*/
}
So far I able to complete steps 1, 2 and 3 but not too sure of a way to add step 4. I may be completely off the mark but any help would be great!
Well one thing you probably won't want to do is allow the error to make it to the top level stream. Even if you do a
catch
you have effectively killed the top level stream. So unless your redirect is doing a hard redirect instead of a a soft one via something like react-router, you won't be able to use this epic any more.Thus I would say that you want most of the logic to be encapsulated within the
switchMap
:The use of
let
above is completely optional, I threw it in to clean up the function. Essentially though you want to contain the error to the inner stream so that it can't halt the outer one. I am not sure whichajax
library you are using but you should also confirm that it will in fact return a coldObservable
otherwise you will need to wrap it in adefer
block to in order for theretryWhen
to work.