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

Compose multiple Rest Links? #264

Closed
sbauch opened this issue Aug 4, 2020 · 6 comments
Closed

Compose multiple Rest Links? #264

sbauch opened this issue Aug 4, 2020 · 6 comments

Comments

@sbauch
Copy link

sbauch commented Aug 4, 2020

I'm wanting to consume two 3rd party APIs from my (react native) app.

My setup looks like this, omitting things like responseTransformer:

const airtableLink = new RestLink({
  uri: 'https://api.airtable.com/v0/app----------------/',
  endpoints: { airtable: 'https://api.airtable.com/v0/app---------------/' },
  headers: {
    'Content-Type': 'application/json',
    Authorization: 'Bearer ---------',
  },
});


const zendeskLink = new RestLink({
  uri: 'https://my.zendesk.com/api/v2/',
  endpoints: { zendesk: 'https://my.zendesk.com/api/v2/' },
  headers: {
    'Content-Type': 'application/json',
    Authorization: `Basic ----------`,
  },
});

const client = new ApolloClient({
  link: ApolloLink.from([airtableLink, zendeskLink]),
  cache: new InMemoryCache(),
});

I then specify endpoints in the @rest directives of all of my queries:

export const ARTICLES_QUERY = gql`
  query Articles {
    articles
      @rest(
        type: "Article"
        path: "help_center/en-us/articles.json"
        endpoint: "zendesk"
      ) {
      id
      body
      title
      voteCount
      labelNames
    }
  }
`;


export const WIDGETS_QUERY = gql`
  query Widgets {
    widgets
      @rest(type: "Widget", path: "Widgets", endpoint: "airtable") {
      id
      name
    }
  }
`;

It seems that all of the queries are routed to the RestLink that is listed first in the ApolloLink.from array? I'm not sure tbh, it's a bit hard to track down what's happening to the queries for the second RestLink.

I recognize this is maybe not what this project is intended for, and I'm definitely using the endpoints map in a way different than intended, but should something like this be possible with apollo client?

@fbartho
Copy link
Collaborator

fbartho commented Aug 4, 2020

hey @sbauch -- definitely the intended way to combine multiple endpoints is within a single RestLink instance.

That's not to say it's impossible for us to enhance apollo-link-rest to support this pattern -- would you mind explaining why you want separate RestLink instances?

Apollo's built-in model includes split -- this allows you to fork a query to be served by different HttpLink instances, so it could equally be used to fork across RestLink Instances.

@sbauch
Copy link
Author

sbauch commented Aug 4, 2020

I need to send different auth headers to the different endpoints, and it initially didn't seem like there was a way to send a different header per endpoint, though perhaps I could use different bodySerializer functions to attach the relevant auth header?

Some part of me feels like having multiple RestLinks like I tried keeps things a bit cleaner, but I may have also been approaching this as rest API link, rather than a more general "rest" link? So it just made sense that, for 2 rest APIs, I would have 2 rest links.

I'm happy to give split a shot though, thanks for the pointer!

@fbartho
Copy link
Collaborator

fbartho commented Aug 4, 2020

@sbauch -- Another relatively easy alternative would be to provide a customFetch function.

Depending on what headers you need to attach, the customFetch would be even easier for attaching headers than using the split link.

@sbauch
Copy link
Author

sbauch commented Aug 4, 2020

I think part of my challenge is that these REST APIs are really more "REST-like", and so in addition to headers, I need to also provide responseTransformers to each that are quite a bit different.

but, I do have a working solution with split! does this seem like what you were suggesting?

const splittableLink = new ApolloLink((operation, forward) => {
  operation.setContext({
    endpoint: ZENDESK_OPERATIONS.includes(operation.operationName)
      ? 'zendesk'
      : 'airtable',
  });
  return forward(operation);
});

const link = splittableLink.split(
  (operation) => {
    return operation.getContext().endpoint === 'zendesk';
  },
  zendeskLink,
  airtableLink,
);

const client = new ApolloClient({
  link,
  cache: new InMemoryCache(),
});

@fbartho
Copy link
Collaborator

fbartho commented Aug 4, 2020

@sbauch yeah -- given your constraints, the split solution is probably best for you!

@willyboy
Copy link

The frustrating thing about this solution is that it doesn’t allow you to call zendesk and airtable in the same query (unless I missed something)

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

No branches or pull requests

3 participants