I made a wrapper for accessing the 'rxjs/observable/dom/ajax' functions with an authentication header. That part went ok.
export const authjax = {
create: urlOrRequest => ajax(typeof urlOrRequest === 'string'
? {url: urlOrRequest, headers: authHeader()} : _.merge({}, urlOrRequest, {headers: authHeader()})
),
get: (url, headers = {}) => ajax.get(url, {...headers, ...authHeader()}),
post: (url, body = {}, headers = {}) => ajax.post(url, body, {...headers, ...authHeader()}),
put: (url, body = {}, headers = {}) => ajax.put(url, body, {...headers, ...authHeader()}),
patch: (url, body = {}, headers = {}) => ajax.patch(url, body, {...headers, ...authHeader()}),
getJSON: (url, headers = {}) => ajax.getJSON(url, {...headers, ...authHeader()})
};
So, this is getting used in place of ajax. Here's an example of it getting used in an epic.
export const getBatchesEpic = (action$, store) =>
action$.ofType(actions.GET_BATCHES)
.switchMap(action => {
const {paginate, refresh} = action;
const paginatorNext = _.get(store.getState(), 'manager.paginator.batches.next');
const usePaginatorNext = paginatorNext && paginate && !refresh;
return authjax.get(usePaginatorNext ? paginatorNext : `${API_URL}/batches/`)
.concatMap(({response}) => {
const incompleteBatches = response.results.filter(batch => !batch.completed);
const checkBatchActions = incompleteBatches.map(batch => checkBatch(batch.id));
return [
{type: actions.BATCHES_RECEIVED, data: response, next: response.next, paginate},
...checkBatchActions
];
})
.catch(error => Observable.of({type: actions.GET_BATCHES_ERROR, error})
);
});
Now, I'm in the first stage of trying to make a simple test pass using just the authjax.get
method. I want 401 responses from the server to get caught by authjax, and for authjax to return a logout action, as well as cancel any following chained methods.
This is my latest attempt for authjax.get
. It works for successful ajax responses, and for non 401 ajax responses. It doesn't return anything, even the logout action, when it hits the 401.
export const authjax = {
create: urlOrRequest => ajax(typeof urlOrRequest === 'string'
? {url: urlOrRequest, headers: authHeader()} : _.merge({}, urlOrRequest, {headers: authHeader()})
),
get: (url, headers = {}) => {
const call = ajax.get(url, {...headers, ...authHeader()});
return call.catch(error => {
if (_.get(error, 'status') === 401) {
console.log('401!!!', Observable.of({type: actions.LOGOUT}));
return Observable.of({type: actions.LOGOUT}).ignoreElements();
}
return call;
});
},
post: (url, body = {}, headers = {}) => ajax.post(url, body, {...headers, ...authHeader()}),
put: (url, body = {}, headers = {}) => ajax.put(url, body, {...headers, ...authHeader()}),
patch: (url, body = {}, headers = {}) => ajax.patch(url, body, {...headers, ...authHeader()}),
getJSON: (url, headers = {}) => ajax.getJSON(url, {...headers, ...authHeader()})
};
I'm reading rxjs docs, but finding that there is an assumption that you would never need to switch out or cancel a stream in a stream. I know there are maybe options where I could handle more in the Epic itself, but I want authjax to be able to take care of its own authentication concerns so I can use it as an import across multiple apps using the same auth.
This is the answer that I have come up with for now.
export const wrapAjax = ({method, args = {}}) => {
const headers = {...args.headers || {}, ...authHeader()};
const call = method
? ajax[method](..._.values(_.omit(args, ['headers'])), headers)
: ajax(_.merge({}, args, {headers}));
return call.catch(error => {
if (_.get(error, 'status') === 401) {
return Observable.throw({...error, action: {type: actions.AUTH_401, error}}).ignoreElements();
}
return call;
});
};
It stops any chain methods if the status is a 401, and hits any later catch statements. The catch statements in the epic sadly have to dispatch the returned action attribute. Not stoked but this is how I ended up moving on for now.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.