reactivecore icon indicating copy to clipboard operation
reactivecore copied to clipboard

Allow customization of GraphQL fetch

Open janus-reith opened this issue 6 years ago • 2 comments

The GraphQL fetch should allow for more custumization:

  • Currently the fetch call is fixed to query elastic50, feels weird to have to use elastic50 as my query name even if I'm using 7.2

  • enforces the usage of a host parameter(which I dont use as the graphql proxy takes care of the host + credentials, therefore resulting in an error for me)

  • Uses content type application/graphql while lots of implementations like Apollo seem to prefer application/json

  • ReactiveBase could take a transformRequest parameter, which seems to be ignored in case graphQLUrl is used.

janus-reith avatar Jul 23 '19 16:07 janus-reith

Simply changing application/graphql to application/json did not work for me and I had issues to get the right encoding. This is how it worked for me:

const fetchGraphQL = (graphQLUrl, url, credentials, app, query) => {

    const mSearchBody = JSON.stringify(query.map(item => JSON.stringify(item)));

    const body = JSON.stringify({
        query: `{ elastic72 { msearch ( index: "${app}", body: ${mSearchBody} ) } }`
    });

    return fetch(graphQLUrl, {
            method: 'POST',
            body,
            headers: {
                'Content-Type': 'application/json',
            },
        })
        .then(res => res.json())
        .then(jsonRes => jsonRes.data.elastic72.msearch)
        .catch((error) => {
            console.error(error);
        });
};

export default fetchGraphQL;

I would need to make use of the host url and credentials parameter and see if they were provided, if yes build a url that should be provided as host parameter to the query in order to include all functionality. Would be interesting to see if the GraphQL proxy you are using would also accept the query in this encoding, if yes I could prepare a PR.

janus-reith avatar Aug 23 '19 08:08 janus-reith

I had the same issue. Forking was not an ideal solution since there are multiple packages involved and keeping in sync would have been painful. I use apollo-server as a backend.

So here is what I did: I used xspy module which allows to modify requests before they are sent, and did this :

import xspy from 'xspy';

xspy.onRequest(request => {
  // Intercept the good request.
  if (
    request.ajaxType === 'xhr' &&
    request.method === 'POST' &&
    request.headers['content-type'] !== 'application/json' &&
    request.body.includes('elastic50')
  ) {
    request.headers.accept = '*/*';
    request.headers['content-type'] = 'application/json';
    // Here you could inject authorization headers.
    request.headers.authorization = `Bearer ${window.localStorage.getItem(
      'token'
    )}`;
    request.body = JSON.stringify({
      // My field is named "elastic" so we rename it here, and strip host argument.
      query: request.body.replace(/elastic50\(.*\)/, 'elastic50:elastic')
    });
  }
});

jide avatar Oct 20 '20 09:10 jide