Apollo Gateway with Subgraph Schemas
The Inigo plugin for Apollo Gateway provides full observability and controls on both the supergraph and all the individual subgraphs. Follow the instructions to get up and running with your gateway.
A working example of this integration is available at https://github.com/inigolabs/workshops/blob/main/apollo-gateway-fed-2-demo
Installation
Inigo supports Node v18 and v20 LTS releases.
- Install the
inigo.js
packagenpm install inigo.js
- Install your platform specific library:
Available libraries:
npm install inigo-linux-amd64
- inigo-linux-amd64
- inigo-linux-arm64
- inigo-darwin-amd64
- inigo-darwin-arm64
- inigo-windows-amd64
Get token
- Set up a service and a token. If you still need one, follow Getting Started.
Configuration
-
Create a
gateway.yaml
configuration file
Replace the service names and urls with your own subgraph configurations.
Any subgraphs omitted from this list will still work as normal, but will not go through the Inigo plugin.kind: Gateway
name: <service_name> # service name created in the previous command
label: <service_label> # optional service label
spec:
services:
- name: accounts
url: "http://localhost:4001/graphql"
- name: reviews
url: "http://localhost:4002/graphql"
- name: products
url: "http://localhost:4003/graphql"
- name: inventory
url: "http://localhost:4004/graphql" -
Apply the gateway configuration
inigo apply gateway.yaml
- When adding or removing subgraphs, the apply command above needs to be rerun and the gateway needs to be restarted.
Integration
The following code contains ApolloServer
, ApolloGateway
, Inigo
, and other supporting objects and libraries to have a complete solution.
The code following is from the example application gateway.js
implementation.
const { ApolloServer } = require('@apollo/server');
const { startStandaloneServer } = require('@apollo/server/standalone');
const { ApolloGateway } = require("@apollo/gateway");
const { Inigo, InigoRemoteDataSource, InigoSchemaManager } = require("inigo.js");
const { readFileSync } = require("fs");
const { resolve } = require("path");
require("dotenv").config()
// If you want to use a locally composed schema:
// 1. Run "inigo compose ./inigo/gateway.yaml > supergraph.graphql"
// 2. Add "LOCAL_COMPOSED_SCHEMA=supergraph.graphql" to the .env
// 3. Start the gateway with "npm run start-gateway"
// 4. If you change your local subgraph schemas, run "inigo compose" again and restart the gateway
var supergraphSchemaConfig;
if(process.env.LOCAL_COMPOSED_SCHEMA) {
console.log("💻 You're using a local federated schema from .env.LOCAL_COMPOSED_SCHEMA");
var cwd = resolve(__dirname, ".");
var supergraphSdl = resolve(cwd, process.env.LOCAL_COMPOSED_SCHEMA);
supergraphSchemaConfig = readFileSync(supergraphSdl, "utf-8");
}
else {
console.log("⛅ You're using a federated schema pulled from Inigo's schema repository");
supergraphSchemaConfig = new InigoSchemaManager()
}
const gateway = new ApolloGateway({
supergraphSdl: supergraphSchemaConfig,
buildService(service) {
return new CustomRemoteDataSource(service, inigo);
}
});
const inigo = new Inigo();
const server = new ApolloServer({
gateway,
plugins: [
inigo.plugin(),
],
introspection: true,
});
startStandaloneServer(server, {
listen: { port: 4000 },
}).then(({ url }) => console.log(`🚀 Supergraph ready at ${url}`));
// Optionally needed for headers to be propagated to the subgraphs
class CustomRemoteDataSource extends InigoRemoteDataSource {
async onBeforeSendRequest({ request, context }) {
if (context.req && context.req.headers) {
// pass all headers to subgraph
Object.keys(context.req.headers || []).forEach(key => {
if (context.req.headers[key]) {
request.http.headers.set(key, context.req.headers[key]);
}
});
}
}
}
Existing RemoteDataSource
If you already have a custom RemoteDataSource
, the InigoDataSourceMixin
provides an easier way to integrate the InigoRemoteDataSource
into your existing code using TypeScript.
new (InigoDataSourceMixin(BaseDataSource, inigo))(...)
In this example code, inigo
is the instance of Inigo
class, and BaseDataSource
is your custom RemoteDataSource
implementation.
Set Up
It is recommended that you have a .env
file set up (as shown in the demo), but you can also use environment variables.
Set Up for a Locally Composed Schema
Here is an example .env
file that sets up a LOCAL_COMPOSED_SCHEMA
variable that can be used to load a composed supergraph that was create with inigo compose
, rover supergraph compose
, or created manually.
INIGO_SERVICE_TOKEN=eyJhbGc...
LOCAL_COMPOSED_SCHEMA=supergraph.graphql
You can use inigo compose
, as documented in the example application as such:
inigo compose inigo/gateway.yaml > supergraph.graphql
Set Up a Composed Schema from the Inigo Schema Registry
Here is an example .env
file that pulls a composed supergraph from the Inigo schema registry.
INIGO_SERVICE_TOKEN=eyJhbGc...