Creating a Custom Apollo Router Core Binary
Compile a custom router binary from source
Learn how to compile a custom binary from Apollo Router Core source, which is required to create custom native Rust plugins for the router.
⚠️ Apollo doesn't recommend creating native plugins for the Apollo Router Core or GraphOS Router, 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.
Instead, for most router customizations, Apollo recommends creating either a Rhai script or an external coprocessor. Both of these customizations are supported by Apollo and provide strong separation of concerns and fault isolation.
If you must create a native plugin, please open a GitHub issue, and Apollo can investigate adding the custom capability to the stock router binary.
Prerequisites
To compile the router, you need to have the following installed:
After you install the above, also install the cargo-xtask
and cargo-scaffold
crates:
1cargo install cargo-xtask
2cargo install cargo-scaffold
1. Create a new project
Use the
cargo-scaffold
command to create a project for your custom router:Bash1cargo-scaffold scaffold https://github.com/apollographql/router.git -r apollo-router-scaffold/templates/base -t main
The
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:Bash1cd starstuff
The generated project has the following layout:
1starstuff
2├── Cargo.toml # Dependencies are declared here
3├── README.md
4├── router.yaml # Router yaml config
5├── src
6│ ├── main.rs # Entry point
7│ └── plugins # Custom plugins are located here
8│ └── mod.rs
9└── xtask # Build support files
10 ├── Cargo.toml
11 └── src
12 └── main.rs
The 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 router with the following command:
1cargo build
The resulting debug binary is located in target/debug/router
.
To create a release build for production environments, use this command instead:
1cargo 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:
Bash1curl -sSL https://supergraph.demo.starstuff.dev/ > supergraph-schema.graphql
Run the router and provide the example schema like so:
Bash1cargo run -- --hot-reload --config router.yaml --supergraph supergraph-schema.graphql
During 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:
Bash1cargo router plugin create hello_world
The command prompts you to choose a starting template:
Bash1Select a plugin template: 2> "basic" 3"auth" 4"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:YAMLrouter.yaml1plugins: 2 starstuff.hello_world: 3 message: "starting my plugin"
Run the router again:
Bash1cargo run -- --hot-reload --config router.yaml --supergraph supergraph-schema.graphql
This time, you should see a log line like the following:
Bash12022-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:
1cargo 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
:
1[dependencies]
2apollo-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:
1 supergraph:
2 listen: 0.0.0.0:4000
Use your APOLLO_KEY
and APOLLO_GRAPH_REF
environment variables to run the router in managed federation.
1 docker build -t my_custom_router .
2 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:
1# Copy configuration for docker image
2COPY router.yaml /dist/config.yaml
3# Copy supergraph for docker image
4COPY my_supergraph.graphql /dist/supergraph.graphql
5
6# [...] and change the entrypoint
7
8# Default executable is the router
9ENTRYPOINT ["/dist/router", "-s", "/dist/supergraph.graphql"]