Creating a custom Apollo Router binary
⚠️ Native Rust plugins are an advanced feature of the Apollo Router. We do not recommend creating them for the following reasons:
- Native plugins require familiarity with programming in Rust.
- Native plugins require compiling a custom router binary from source, which can introduce unexpected behavior in your router that's difficult to diagnose and support.
For most router customizations, we recommend instead creating a Rhai script or external coprocessor. Both of these customization types provide strong separation of concerns and fault isolation.
If a native plugin seems necessary for your use case, please open an issue so we can investigate adding the required functionality to the stock router binary.
Note: The Apollo Router is made available under the Elastic License v2.0 (ELv2). This applies to its source code and all distributions. For details, see our licensing page.
Prerequisites
To compile the Apollo Router, you need to have the following installed:
After you install the above, also install the cargo-xtask
and cargo-scaffold
crates:
cargo install cargo-xtaskcargo install cargo-scaffold
1. Create a new project
Use the
cargo-scaffold
command to create a project for your custom router:cargo-scaffold scaffold https://github.com/apollographql/router.git -r apollo-router-scaffold/templates/base -t mainThe
cargo-scaffold
command prompts you for some configuration settings. For the purposes of this tutorial, set your project's name tostarstuff
.After your project is created, change to the
starstuff
directory:cd starstuff
The generated project has the following layout:
starstuff├── Cargo.toml # Dependencies are declared here├── README.md├── router.yaml # Router yaml config├── src│ ├── main.rs # Entry point│ └── plugins # Custom plugins are located here│ └── mod.rs└── xtask # Build support files├── Cargo.toml└── src└── main.rs
The Apollo Router uses an auto-discovery mechanism for plugins, so any plugins you add via dependency are automatically available to the Router at runtime.
2. Compile the router
Create a debug build of the Apollo Router with the following command:
cargo build
The resulting debug binary is located in target/debug/router
.
To create a release build for production environments, use this command instead:
cargo build --release
The resulting release binary is now located in target/release/router
.
3. Run the compiled binary
Now you can test out your compiled router with an example supergraph schema.
Download the example schema with the following command:
curl -sSL https://supergraph.demo.starstuff.dev/ > supergraph-schema.graphqlRun the router and provide the example schema like so:
cargo run -- --hot-reload --config router.yaml --supergraph supergraph-schema.graphqlDuring development, it's helpful to use
cargo run
to run the router.
If you're using managed federation, you set the APOLLO_KEY
and APOLLO_GRAPH_REF
environment variables instead of specifying the supergraph schema as a file. For details, see this section.
4. Create a plugin
From within your project directory, scaffold a new plugin with the following command:
cargo router plugin create hello_worldThe command prompts you to choose a starting template:
Select a plugin template:> "basic""auth""tracing"The available templates are:
basic
- a barebones pluginauth
- an authentication plugin for making an external calltracing
- a telemetry plugin that adds a custom metric span and a log message
For the purposes of this tutorial, choose
basic
.Add configuration options for the created plugin to your
router.yaml
file:router.yamlplugins:starstuff.hello_world:message: "starting my plugin"Run the router again:
cargo run -- --hot-reload --config router.yaml --supergraph supergraph-schema.graphqlThis time, you should see a log line like the following:
2022-05-21T09:16:33.160288Z INFO router::plugins::hello_world: starting my plugin
Nice work! You now have a custom router binary with an associated plugin. Next, you can extend the plugin with the functionality you need or add more plugins.
Removing a plugin
To remove a previously added plugin from your router project, use the following command:
cargo router plugin remove hello_world
Note that depending on the structure of your plugin, the command might fail to remove all of its associated files.
Memory allocator
On Linux the apollo-router
crate sets jemalloc
as the global memory allocator for Rust
to reduce memory fragmentation.
Future versions may do so on more platforms, or switch to yet a different allocator.
This is enabled by default and controlled by a global-allocator
Cargo feature flag.
If you want to choose a different allocator, disable it in your Cargo.toml
:
[dependencies]apollo-router = {version = "[…]", default-features = false}
If you make a library crate, also specify default-features = false
in order to leave the choice open for the eventual executable crate.
(Cargo default features are only disabled if all dependents specify default-features = false
.)
Docker
You can use the provided Dockerfile to build a release container.
Make sure your router is configured to listen to 0.0.0.0
so you can query it from outside the container:
supergraph:listen: 0.0.0.0:4000
Use your APOLLO_KEY
and APOLLO_GRAPH_REF
environment variables to run the router in managed federation.
docker build -t my_custom_router .docker run -e APOLLO_KEY="your apollo key" -e APOLLO_GRAPH_REF="your apollo graph ref" my_custom_router
Otherwise add a COPY
step to the Dockerfile, and edit the entrypoint:
# Copy configuration for docker imageCOPY router.yaml /dist/config.yaml# Copy supergraph for docker imageCOPY my_supergraph.graphql /dist/supergraph.graphql# [...] and change the entrypoint# Default executable is the routerENTRYPOINT ["/dist/router", "-s", "/dist/supergraph.graphql"]