Apollo-server: schema stitching question. modify initial request and pass it to remoteServer

Created on 26 Dec 2017  路  8Comments  路  Source: apollographql/apollo-server

I don't know if it's right to ask here... but I couldn't find anywhere.
There is one api gateway graphql/express server(get all the request from clients) and
multiple microservice graphql/express servers(auth, business logic1 , business logic2, business logic3 etc) that are connected to this gateway using schema stitching.(mergeSchema)

  1. if client requests with Bearer token, normally I can retrieve token from headers and use context to pass down authorization token and use it at the resolvers. But How can I pass this to remote server?
    It seems like modifying request object doesn't affect anything.(it only affects the object in gateway server)
    It seems like copying graphql specific data only and send it to remoteServer.(Therefore, I couldn't get the Authorization header at my remoteServer)
    so far, I couldn't find a way to pass my jwt token from api gateway to other remote servers.

Am I thinking something wrong?

Most helpful comment

@lonyele I think I was just able to solve this using Apollo Link with setContext.

In your gateway:

  const ContextLink = setContext((request, previousContext) => ({
    headers: {
      authorization: previousContext.graphqlContext.headers.authorization,
    },
  }));
  const AuthLink = new HttpLink({
    uri: 'http://localhost:3001/graphql',
    fetch,
  });
  const AuthSchema = makeRemoteExecutableSchema({
    schema: await introspectSchema(AuthLink),
    link: ApolloLink.from([ContextLink, AuthLink]),
  });

  const mergedSchema = mergeSchemas({
    schemas: [AuthSchema, ...otherSchemas],
  });

Now Auth microservice has token available in headers.

All 8 comments

@lonyele I think I was just able to solve this using Apollo Link with setContext.

In your gateway:

  const ContextLink = setContext((request, previousContext) => ({
    headers: {
      authorization: previousContext.graphqlContext.headers.authorization,
    },
  }));
  const AuthLink = new HttpLink({
    uri: 'http://localhost:3001/graphql',
    fetch,
  });
  const AuthSchema = makeRemoteExecutableSchema({
    schema: await introspectSchema(AuthLink),
    link: ApolloLink.from([ContextLink, AuthLink]),
  });

  const mergedSchema = mergeSchemas({
    schemas: [AuthSchema, ...otherSchemas],
  });

Now Auth microservice has token available in headers.

I don't know why I couldn't see this earlier, but It seems like It would work with your method. I'll try this soon. Thanks a lot!!

How about something from the mergedSchemas altering headers on the response from above? @booboothefool any ideas how could I accomplish this?

When trying to do this I always get "message": "Cannot read property 'Authorization' of undefined", I've tried with caps and without, also just matching all headers headers: previousContext.graphqlContext.headers, but it still doesn't pass.

Edit:

This fixed it:

schema.ts:

const ContextLink = setContext((request, previousContext) => ({
    headers: {
      authorization: previousContext.graphqlContext.headers.authorization,
    }
  }));

server.ts:

app.use(
    '/graphql',
    bodyParser.json(),
    graphqlExpress(async request => ({
      schema: await makeMergedSchema(),
      context: {
        headers: request ? request.headers : null
      }
    }))
  );

what if you want to pass in a whole context? For example, authorization server returns policies that are tied to the user, i dont want to send the token down to my stitched serve, i want to pass down the user object i set at my context.

This might sound dumb but where is setContext() coming from?

This might sound dumb but where is setContext() coming from?

I struggled with this also, he is using apollo-link-context

import { setContext } from "apollo-link-context";
import { ApolloLink } from 'apollo-link';

How do you use it in the service that you have stitched?
Something like this:
context: ({ headers }) => {}

Was this page helpful?
0 / 5 - 0 ratings