Apollo Gateway (JS Middleware)
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.
Installation
- 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.
Integration
Create a gateway.yml 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.```yaml
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.yml
- When adding or removing subgraphs, the apply command above needs to be rerun and the gateway needs to be restarted.
Integration
const { ApolloServer } = require("@apollo/server");
const { startStandaloneServer } = require("@apollo/server/standalone");
const { ApolloGateway, IntrospectAndCompose } = require("@apollo/gateway");
const {
InigoPlugin,
InigoRemoteDataSource,
InigoFetchGatewayInfo,
} = require("inigo.js");
// Build schema from sdls : if using schema registry this can be omitted
const supergraphSdl = new IntrospectAndCompose({
subgraphs: [
{ 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" },
],
});
// INIGO: use InigoRemoteDataSource instead of RemoteGraphQLDataSource.
// INIGO: instead of 'willSendRequest' use 'onBeforeSendRequest'
// INIGO: instead of 'didReceiveResponse' use 'onAfterReceiveResponse'.
// INIGO: Signatures of the callbacks are same.
class CustomRemoteDataSource extends InigoRemoteDataSource {
async onBeforeSendRequest({ request, context }) {
if (context.req && context.req.headers) {
// pass all headers to subgraphs
Object.keys(context.headers || []).forEach((key) => {
if (context.headers[key]) {
request.http.headers.set(key, context.headers[key]);
}
});
}
}
async onAfterReceiveResponse({ request, response, context }) {
return response;
}
}
(async () => {
// INIGO: creates the InigoPlugin instance
// INIGO: InigoPlugin must be instantiated before ApolloGateway is started
const inigoPlugin = InigoPlugin();
// INIGO: execute InigoFetchGatewayInfo as early as possible and use the result as a param for your custom data source.
// If gateway kind configuration is missing this call will fail.
const info = await InigoFetchGatewayInfo();
const gateway = new ApolloGateway({
supergraphSdl: supergraphSdl,
buildService(service) {
// INIGO: this is required to get sub-graph visibility.
return new CustomRemoteDataSource(service, info, true); // INIGO: last param if optional. Set "true" if you want Inigo to make SDL queries to subgraphs
},
});
const server = new ApolloServer({
gateway: gateway,
plugins: [
// INIGO: pass the plugin to ApolloServer
inigoPlugin,
],
});
const { url } = await startStandaloneServer(server, {
context: async ({ req }) => ({ req }),
});
console.log(`🚀 Server ready at ${url}`);
})();
Execution
INIGO_SERVICE_TOKEN="inigo-service-token" npm start
Other optional available environment flags:
INIGO_ENABLE=[true, false] # default is true
LOG_LEVEL=[disabled, debug, info, error, fatal] # default log level is info
Limitation
- Alpine docker support is currently unavailable.