DEV Community

Harshit Kumar
Harshit Kumar

Posted on • Updated on • Originally published at harshitkumar.co.in

Creating a Proxy for your GraphQL Server

I needed to create a proxy server for my GraphQL service to be able to make some decisions before reaching my service.

This article will document how you can do the same with minimal amount of code 😏
We'll be leveraging awesome utilities provided by graphql-tools

Installation

npm init -y
npm i @graphql-tools/delegate @graphql-tools/utils @graphql-tools/wrap apollo-server cross-undici-fetch graphql typescript
Enter fullscreen mode Exit fullscreen mode

Create an executor

Executor is a function used capable of retrieving GraphQL results (both introspection & fetching results during a query's execution).

In the executor, I've defined the GraphQL service's URL which I want to proxy - https://graphql.anilist.co/ (an open API to fetch your favourite Anime characters)

const executor =  async ({ document , variables, context }: {document: any, variables: any, context: any}) => {
    const query = print(document)
  const fetchResult = await fetch('https://graphql.anilist.co/', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      ...context?.headers
    },
    body: JSON.stringify({ query, variables })
  })
  return fetchResult.json()
}
Enter fullscreen mode Exit fullscreen mode

Define applicationProxyResolver

This function is passed to wrapSchema method. In this method, you should be able to make some decisions. For example - I wanted to validate some headers & only honour the requests if they had these headers. We'll use delegateToSchema to delegate the entire request to our original GraphQL service.

export const applicationProxyResolver = ({
    subschemaConfig,
    operation,
    transformedSchema,
}: {
    subschemaConfig: any,
    operation: any,
    transformedSchema: any,
}) => {
    return (_parent: any, _args: any, context: any, info: any) => {
        return delegate.delegateToSchema({
            schema: subschemaConfig,
            operation,
            operationName: info!.operation!.name!.value,
            context,
            info,
            transformedSchema,
        });
    };
}
Enter fullscreen mode Exit fullscreen mode

Let's fire up the graphQL proxy server 🚀

const init = async () => {
    const schema = wrapSchema({
        schema: await introspectSchema(executor),
        executor,
        createProxyingResolver: applicationProxyResolver
    });

    const server = new ApolloServer({ 
        schema,
    });

    // The `listen` method launches a web server.
    server.listen(4001).then(({ url }) => {
        console.log(`🚀  Server ready at ${url}`);
    });

}

init();
Enter fullscreen mode Exit fullscreen mode

Proxy

You can find this code at Github.

Is there an easier way to do this? Please comment & let me know 😁

Discussion (0)