Ajax config & intercept
vimniky opened this issue ยท 17 comments
Is there a way to create a pre configured ajax instance, so that I don't need to configure it over and over again ?
For example:
import ajax from 'rxjs/Observable/dom/ajax'
const myAjax = ajax.create({url: '/api/xxx', header: {widthCredential: true, ...}})
// Now myAjax will setup widthCredential = true for all the related outgoing ajax request
// so that I can just:
myAjax.get('/api/xxx')
myAjax.post('/api/xxx', body)
// Instead of
ajax.get({url: '/api/xxx', header: {widthCredential: true, ...}})
ajax.post({url: '/api/xxx', body: data, header: {widthCredential: true, ...}})
BTW how can I intercept all http requests or responses in a single place using rxjs' ajax api ?
Here's how the axios library intercepts http requests and responses:
// Add a request interceptor
axios.interceptors.request.use(function (config) {
// Do something before request is sent
return config;
}, function (error) {
// Do something with request error
return Promise.reject(error);
});
// Add a response interceptor
axios.interceptors.response.use(function (response) {
// Do something with response data
return response;
}, function (error) {
// Do something with response error
return Promise.reject(error);
});
Thanks !
I'm also interested in how this is solved?
I'm planning on writing a simple http wrapper singleton service around ajax to solve this issue. Will share when I have it completed
I am also very interested in this. I am really wondering if there's an ongoing plan for this issue. I am interested in contributing to adding this functionality. I might have a simple solution to it, and I can work on it very soon :)
Cheers!
So I am currently using Rxjs in one of my projects and I was using rxjs/ajax. However I realized that rxjs/ajax doesn't have interceptors. So out of curiosity I forked rxjs and implemented interceptors. The usage that I came up with (from my project :D) was that I added an operator ajaxInterceptors which can be called using array of (request interceptor array or a request interceptor or none), and (response interceptor array or a response interceptor or none), also more interceptors can be added using few methods for each request (interceptors for GET requests and so on).
My question is:
Is is an ideal implementation for ajax interceptors for rxjs and if so, will it be accepted, once unit tests and performance tests are complete?
update?
Would be great to have an ability to hook to/intercept all the ajax requests.
Is there any way to do it now?
No luck?
any update on this?
any update on this? is there a plan to add interceptors ?
My application is using react + redux-observable
... Here is my workaround see if it help...
import { createStore, applyMiddleware } from 'redux'
import { ajax } from 'rxjs/ajax'
import { createEpicMiddleware } from 'redux-observable'
const myConfig = {
X-Platform: 'desktop',
X-Session-Id: 'xxxxxxx'
}
const epicMiddleware = createEpicMiddleware({
dependencies: {
ajax: config => {
const customConfig = {
...config,
headers: {
...myConfig,
...config.headers
}
}
return ajax({ ...customConfig })
}
}
})
...
......
store = createStore(
rootReducer,
initialState,
applyMiddleware(epicMiddleware)
)
Epics:
export const addToFavorites = (action$, state$, { ajax }) =>
action$.pipe(
ofType(actionsTypes.ADD_TO_FAVORITES),
mergeMap(action => {
const currentUserAccessToken =
state$.value.userReducer.currentUserAccessToken
const userId = state$.value.userReducer.currentUserData.id
return ajax({
method: 'PUT',
headers: {
Authorization: `Bearer ${currentUserAccessToken}`,
'Content-Type': 'application/json'
},
url:
API_USER_ENDPOINT +
`/users/${userId}/favorite_restaurant_ids/${
action.restaurantId
}`
}).pipe(
map(() => {
const userId = state$.value.userReducer.currentUserData.id
return actions.getFavorites(userId)
}),
catchError(err =>
of(actions.epicErrorHandler(err, action.type))
)
)
})
)
By doing this, all the request i send will automatically insert X-Platform
and X-Session-Id
into the header
maybe using more pipe to make more interception..
You can still use Axios with interceptor and use fromPromise
to create an Observable.
In my case i created a function for that.
export function ajaxObs(params: {
[key: string]: any;
url: string;
method?: string;
body?: any;
headers?: { [key: string]: string };
responseType?: string;
}) {
const {
url,
method,
body,
headers = {
"Content-Type": "application/json",
...(Cookies.get("accessToken") && {
Authorization: `Bearer ${Cookies.get("accessToken")}`,
}),
},
responseType,
} = params;
const apiBaseUrl: string = https://mycustomurl.com/
// creation observable
const ajax$: Observable<AjaxResponse | Observable<AjaxError>> = ajax({
url: `${apiBaseUrl}${url}`,
method: method ? method : "GET",
async: true,
headers: headers,
body: body,
...(responseType && { responseType: responseType }),
})
return ajax$;
}
I hope this will help you
I'm on the fence about this feature. I've seen interceptors be useful, however, it also means introducing global, mutable state (at least in the proposed solution, or in existing prior art). In other words, if a third party adds an interceptor like ajax.request.interceptors.push(fn)
, then your code, and worse, other third party code that wants to use ajax is now being intercepted.
I'm more inclined to say a better design would be to have a factory that creates an instance of ajax
that allows users to register interceptors. However, then we're in a situation where maybe it's desirable to intercept ajax requests from third party libraries (perhaps to proxy them or something) and now you can't. I suppose a service worker might be a solution there.
If we had use cases we all agreed on, then perhaps we could implement something. In the mean time, as a workaround, I'd recommend just wrapping it in your own function that amended the request/response as necessary.
Core Team: General lack of interest in this feature as of right now.
@benlesh: I'll think about the problem though, since it seems like something a lot of people are asking for.
I'm more inclined to say a better design would be to have a factory that creates an instance of ajax that allows users to register interceptors.
I tend to prefer these interceptors capable factories instead of a global solution.
What could be provided instead is a generator of such factories.
I have created a sample wrapper for both functional and class-based HTTP services over rxjs ajax to have both before and after interceptors.
https://gist.github.com/maxgaurav/48e1f309fd2afb2ab55c558c3e63d1dc
Hope this helps.