[Federation] How to merge schema from gateway itself.
See original GitHub issueIn short, is there a way to implement Apollo Federation such that the gateway itself has it’s own schema?
(EDIT) TLDR No, the gateway can’t also be a federated service.
Federating Apollo Server where the gateway itself has a schema
@apollo/gateway@0.6.5
@apollo/federation@0.6.2
Expected Behavior
When I am instantiating my Apollo Gateway server, I expect that I should be able to merge schemas from federated services, as well as the schema from the gateway itself.
Actual Behavior
The gateway server fails to mount the /graphql
route because it is expecting all of the services to be currently running before it does so.
On run time, the following error is printed to the console:
POST /graphql 404 11.251 ms - 147
Encountered error when loading gateway at http://localhost:8000/graphql: invalid json response body at http://localhost:8000/graphql reason: Unexpected token < in JSON at position 0
[DEBUG] Fri Jun 07 2019 12:11:07 GMT-0400 (Eastern Daylight Time) apollo-gateway: Configuration loaded for Gateway
[DEBUG] Fri Jun 07 2019 12:11:07 GMT-0400 (Eastern Daylight Time) apollo-gateway: Composing schema from service list:
remote-svc
TypeError: schema.toConfig is not a function
at Object.composeServices (/gateway-app/node_modules/@apollo/federation/dist/composition/compose.js:191:67)
at Object.composeAndValidate (/gateway-app/node_modules/@apollo/federation/dist/composition/composeAndValidate.js:13:41)
at ApolloGateway.createSchema (/gateway-app/node_modules/@apollo/gateway/dist/index.js:90:47)
at ApolloGateway.<anonymous> (/gateway-app/node_modules/@apollo/gateway/dist/index.js:81:22)
at Generator.next (<anonymous>)
at fulfilled (/gateway-app/node_modules/@apollo/gateway/dist/index.js:4:58)
at process._tickCallback (internal/process/next_tick.js:68:7)
Source Code
const url = new URL(`redis://${REDIS_URL}:${REDIS_PORT}/${REDIS_DATABASE}`).toString()
const cache = new RedisCache({ url })
const context = ({ req }) => {
if (!(req.user || req.headers.authorization === ROUTE_AUTH)) {
throw new AuthenticationError('Not authenticated')
}
return { user: req.user, req: req }
}
try {
const loadGateway = async () => {
try {
const { schema, executor } = await gateway.load()
return { schema, executor }
} catch (err) {
console.error(err)
return null
}
}
const gateway = new ApolloGateway({
debug: process.env.ENV !== 'prod',
serviceList: [
{ name: 'gateway', url: `${GATEWAY_HOSTNAME}/graphql` },
{ name: 'remote-svc', url: `${REMOTE_SERVICE_HOSTNAME}/graphql` },
],
})
const { schema, executor } = loadGateway()
const server = new ApolloServer({
schema,
executor,
cache,
dataSources,
engine: { apiKey: ENGINE_API_KEY },
tracing: true,
context,
})
server.applyMiddleware({ app })
} catch (err) {
console.error(err)
}
Justification
The reason for implementing our gateway server this way is to primarily for ease of authentication.
Our gateway server performs all authentication so that we do not have to expend an unnecessary round trip to authenticate a user before executing their request.
Issue Analytics
- State:
- Created 4 years ago
- Comments:7 (3 by maintainers)
Top GitHub Comments
After migration from Schema Stitching to Federation, we tried several ways to keep the Gateway keeps its own schema. We couldn’t separate the schema away the Gateway for some reasons. Finally, we have to start 2 GraphQL server in same server with different port and path. The Federation GraphQL server must be run before Gateway GraphQL server started.
/graphq-extended
on port3001
./graphql
on port3000
.We haven’t found any better solution but currently it works 🥇 🔥
Here’s the implementation:
Exactly that.
Okay, so the solution here is to move the schema from the gateway server to another service.
Thanks for confirming that!