Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ajax config & intercept #2686

Open
ghost opened this issue Jun 20, 2017 · 17 comments
Open

Ajax config & intercept #2686

ghost opened this issue Jun 20, 2017 · 17 comments

Comments

@ghost
Copy link

ghost commented Jun 20, 2017

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 !

@ghost ghost changed the title Ajax config Ajax config & intercept Jun 21, 2017
@macnibblet
Copy link

I'm also interested in how this is solved?

@evanjmg
Copy link

evanjmg commented May 28, 2018

I'm planning on writing a simple http wrapper singleton service around ajax to solve this issue. Will share when I have it completed

@Shehats
Copy link

Shehats commented Aug 24, 2018

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!

@Shehats
Copy link

Shehats commented Aug 27, 2018

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?

@kedwin
Copy link

kedwin commented Oct 31, 2018

update?

@maxevilmind
Copy link

Would be great to have an ability to hook to/intercept all the ajax requests.
Is there any way to do it now?

@shobishani
Copy link

No luck?

@tohbansoon
Copy link

any update on this?

@Yene-Me
Copy link

Yene-Me commented Dec 30, 2019

any update on this? is there a plan to add interceptors ?

@tohbansoon
Copy link

tohbansoon commented Dec 31, 2019

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

@0length
Copy link

0length commented Jan 16, 2020

maybe using more pipe to make more interception..

@gugadev
Copy link

gugadev commented May 5, 2020

You can still use Axios with interceptor and use fromPromise to create an Observable.

@Vincent-Alibert
Copy link

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

@benlesh
Copy link
Member

benlesh commented Jan 12, 2022

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.

@benlesh benlesh added the AGENDA ITEM Flagged for discussion at core team meetings label Jan 12, 2022
@benlesh
Copy link
Member

benlesh commented Jan 12, 2022

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.

@benlesh benlesh removed the AGENDA ITEM Flagged for discussion at core team meetings label Jan 12, 2022
@grimly
Copy link

grimly commented Feb 3, 2022

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.

@maxgaurav
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests