Skip to main content

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 package
    npm install inigo.js
  • Install your platform specific library:
    npm install inigo-linux-amd64
    Available libraries:
    • 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.