Releases: apollographql/router
v0.14.0
❗ BREAKING ❗
Regex allow_any_origin
behavior changed (PR #1444)
Setting allow_any_origin
to true in the router configuration would previously automatically mirror the requested headers.
If you relied on this behavior, you now also need to set allow_any_header
to true
, as explained in the CORS documentation.
server:
cors:
allow_any_origin: true
allow_any_header: true # mirror client's headers
The default CORS headers configuration of the router allows content-type
, apollographql-client-version
and apollographql-client-name
.
By @o0Ignition0o in #1444
Modify the plugin new
method to pass an initialisation structure (PR #1446)
This change alters the new
method for plugins to pass a PluginInit
struct.
We are making this change so that we can pass more information during plugin startup. The first change is that in addition to passing
the plugin configuration, we are now also passing the router supergraph sdl (Schema Definition Language) as a string.
There is a new example (supergraph_sdl
) which illustrates how to use this new capability.
Remove the generic stream type from RouterResponse
and ExecutionResponse
(PR #1420)
This generic type complicates the API with limited benefit because we use BoxStream
everywhere in plugins:
RouterResponse<BoxStream<'static, Response>>
->RouterResponse
ExecutionResponse<BoxStream<'static, Response>>
->ExecutionResponse
Remove the HTTP request from QueryPlannerRequest
(PR #1439)
The content of QueryPlannerRequest
is used as argument to the query planner and as a cache key,
so it should not change depending on the variables or HTTP headers.
Change PluggableRouterServiceBuilder
methods (PR #1437)
with_naive_introspection
and with_defer_support
where two parameter-less methods
of this builder that enabled boolean configuration flags.
They have been removed and replaced by with_configuration
which takes Arc<apollo_router::Configuration>
.
A Configuration
value can be created from various formats by deserializing with serde
.
The removed methods correspond to server.introspection
and server.experimental_defer_support
configuration keys respectively.
By @SimonSapin in #1437
Changes to the SchemaKind
enum (PR #1437)
The Instance
variant is replaced with a variant named String
that contains…
a String
instead of Box<apollo_router::Schema>
,
so you no longer need to parse the schema before giving it to the router.
Similarly, the Stream
variant now contains a stream of String
s
instead of a stream of already-parsed Schema
s.
By @SimonSapin in #1437
Schema
no longer implements FromStr
(PR #1437)
This means that str.parse::<apollo_router::Schema>()
is no longer available.
If you still need a parsed Schema
(see above),
use apollo_router::Schema(str, &configuration)
instead.
To use the default apollo_router::Configuration
you can call apollo_router::Schema(str, &Default::default())
.
By @SimonSapin in #1437
🚀 Features
Publish helm chart to OCI registry (PR #1447)
When we make a release, publish our helm chart to the same OCI registry that we use for our docker images.
For more information about using OCI registries with helm, see the helm documentation.
Configure Regex based CORS rules (PR #1444)
The router now supports regex based CORS rules, as explained in the docs
It also supports the allow_any_header
setting that will mirror client's requested headers.
server:
cors:
match_origins:
- "https://([a-z0-9]+[.])*api[.]example[.]com" # any host that uses https and ends with .api.example.com
allow_any_header: true # mirror client's headers
The default CORS headers configuration of the router allows content-type
, apollographql-client-version
and apollographql-client-name
.
By @o0Ignition0o in #1444
Add support of error section in telemetry to add custom attributes (PR #1443)
The telemetry is now able to hook at the error stage if router or a subgraph is returning an error. Here is an example of configuration:
telemetry:
metrics:
prometheus:
enabled: true
common:
attributes:
subgraph:
all:
errors: # Only works if it's a valid GraphQL error
include_messages: true # Will include the error message in a message attribute
extensions: # Include extension data
- name: subgraph_error_extended_type # Name of the attribute
path: .type # JSON query path to fetch data from extensions
Experimental support for the @defer
directive (PR #1182)
The router can now understand the @defer
directive, used to tag parts of a query so the response is split into
multiple parts that are sent one by one.
To activate it, add this option to the configuration file:
server:
experimental_defer_support: true
Rewrite the caching API (PR #1281)
This introduces a new asynchronous caching API that opens the way to multi level caching (in memory and
database). The API revolves around an Entry
structure that allows query deduplication and lets the
client decide how to generate the value to cache, instead of a complicated delegate system inside the
cache.
🐛 Fixes
Update serialization format for telemetry.tracing.otlp.grpc.metadata (PR #1391)
The metadata format now uses IndexMap<String, Vec<String>>
.
Update the scaffold template so it targets router v0.14.0 (PR #1431)
The cargo scaffold template will target the latest version of the router.
By @o0Ignition0o in #1248
Selection merging on non-object field aliases (PR #1406)
Fixed a bug where merging aliased fields would sometimes put null
s instead of expected values.
By @o0Ignition0o in #1432
A Rhai error instead of a Rust panic ([PR #1414 https://github.com//pull/1414))
In Rhai plugins, accessors that mutate the originating request are not available when in the subgraph phase. Previously, trying to mutate anyway would cause a Rust panic. This has been changed to a Rhai error instead.
By @SimonSapin in #1414
Optimizations (PR #1423)
- Do not clone the client request during query plan execution
- Do not clone the usage reporting
- Avoid path allocations when iterating over JSON values
The benchmarks show that this change brings a 23% gain in requests per second compared to the main branch.
do not perform nested fetches if the parent one returned null (PR #1332
In a query of the form:
mutation {
mutationA {
mutationB
}
}
If mutationA
returned null, we should not execute mutationB
.
🛠 Maintenance
📚 Documentation
Updates wording and formatting of README.md
By @EverlastingBugstopper in #1445
What's Changed
- CI: Upgrade the macOS image version by @SimonSapin in #1418
- Remove the ...
v0.12.1-alpha-defer4
How to test @defer
support in the router
Add this to the configuration file:
server:
experimental_defer_support: true
v0.12.1-alpha-defer3
How to test @defer
support in the router
Add this to the configuration file:
server:
experimental_defer_support: true
Add this to the supergraph schema:
directive @defer(
label: String
if: Boolean
) on FRAGMENT_SPREAD | INLINE_FRAGMENT
v0.12.1-alpha-defer2
v0.12.1-alpha-defer
v0.12.0
[0.12.0] - 2022-08-18
❗ BREAKING ❗
Move experimental.rhai
out of experimental
PR #1365
You will need to update your YAML configuration file to use the correct name for rhai
plugin.
- plugins:
- experimental.rhai:
- filename: /path/to/myfile.rhai
+ rhai:
+ scripts: /path/to/directory/containing/all/my/rhai/scripts (./scripts by default)
+ main: <name of main script to execute> (main.rhai by default)
You can now modularise your rhai code. Rather than specifying a path to a filename containing your rhai code, the rhai plugin will now attempt to execute the script specified via main
. If modules are imported, the rhai plugin will search for those modules in the scripts
directory. for more details about how rhai makes use of modules, look at the rhai documentation.
The simplest migration will be to set scripts
to the directory containing your myfile.rhai
and to rename your myfile.rhai
to main.rhai
.
🐛 Fixes
The opentelemetry-otlp crate needs a http-client feature PR #1392
The opentelemetry-otlp crate only checks at runtime if a HTTP client was added through
cargo features. We now use reqwest for that.
Expose the custom endpoints from RouterServiceFactory (PR #1402)
Plugin HTTP endpoints registration was broken during the Tower refactoring. We now make sure that the list
of endpoints is generated from the RouterServiceFactory
instance.
🛠 Maintenance
Dependency updates PR #1389 PR #1394 PR #1395
Dependency updates were blocked for some time due to incompatibilities:
- #1389: the router-bridge crate needed a new version of
deno_core
in its workspace that would not fix the version ofonce_cell
. Now that it is done we can updateonce_cell
in the router - #1395:
clap
at version 3.2 changed the way values are extracted from matched arguments, which resulted in panics. This is now fixed and we can updateclap
in the router and related crates - #1394: broader dependency updates now that everything is locked
- #1410: revert tracing update that caused two telemetry tests to fail (the router binary is not affected)
v0.11.0
❗ BREAKING ❗
Relax plugin api mutability PR #1340 PR #1289
the Plugin::*_service()
methods were taking a &mut self
as argument, but since
they work like a tower Layer, they can use &self
instead. This change
then allows us to move from Buffer to service factories for the query
planner, execution and subgraph services.
Services are now created on the fly at session creation, so if any state must be shared
between executions, it should be stored in an Arc<Mutex<_>>
in the plugin and cloned
into the new service in the Plugin::*_service()
methods.
🚀 Features
Add support to add custom resources on metrics. PR #1354
Resources are almost like attributes but more global. They are directly configured on the metrics exporter which means you'll always have these resources on each of your metrics. This functionality can be used to, for example,
apply a service.name
to metrics to make them easier to find in larger infrastructure, as demonstrated here:
telemetry:
metrics:
common:
resources:
# Set the service name to easily find metrics related to the apollo-router in your metrics dashboards
service.name: "apollo-router"
🐛 Fixes
Fix fragment on interface without typename PR #1371
When the subgraph doesn't return the __typename
and the type condition of a fragment is an interface, we should return the values if the entity implements the interface
Fix detection of an introspection query PR #1370
A query that only contains __typename
at the root will now special-cased as merely an introspection query and will bypass more complex query-planner execution (its value will just be Query
).
Accept nullable list as input PR #1363
Do not throw a validation error when you give null
for an input variable of type [Int!]
.
🛠 Maintenance
Replace Buffers of tower services with service factories (PR #1289 PR #1355)
Tower services should be used by creating a new service instance for each new session
instead of going through a Buffer
.
Execute the query plan's first response directly (PR #1357)
The query plan was previously executed in a spawned task to prepare for the @defer
implementation, but we can actually
generate the first response right inside the same future.
Remove deprecated failure
crate from the dependency tree PR #1373
This should fix automated reports about GHSA-jq66-xh47-j9f3.
Render embedded Sandbox instead of landing page (PR #1369)
Open the router URL in a browser and start querying the router from the Apollo Sandbox.
By @mayakoneval in #1369
📚 Documentation
Various documentation edits (PR #1329)
By @StephenBarlow in #1329
v0.10.0
❗ BREAKING ❗
Change configuration for custom attributes for metrics in telemetry plugin (PR #1300)
To create a distinction between subgraph metrics and router metrics, a distiction has been made in the configuration. Therefore, a new configuration section called router
has been introduced and Router-specific properties are now listed there, as seen here:
telemetry:
metrics:
common:
attributes:
- static:
- - name: "version"
- value: "v1.0.0"
- from_headers:
- - named: "content-type"
- rename: "payload_type"
- default: "application/json"
- - named: "x-custom-header-to-add"
+ router:
+ static:
+ - name: "version"
+ value: "v1.0.0"
+ request:
+ header:
+ - named: "content-type"
+ rename: "payload_type"
+ default: "application/json"
+ - named: "x-custom-header-to-add"
Rename http_compat
to http_ext
(PR #1291)
The module provides extensions to the http
crate which are specific to the way we use that crate in the router. This change also cleans up the provided extensions and fixes a few potential sources of error (by removing them)
such as the Request::mock()
function.
Rework the entire public API structure (PR #1216, PR #1242, PR #1267, PR #1277, PR #1303)
-
Many items have been removed from the public API and made private.
If you were relying on these previously-public methods and find that they are no longer available, please open an issue with your use case so we can consider how we want to re-introduce them. -
Many re-exports have been removed.
Most notably from the crate root and all of theprelude
modules.
These items now need to be imported from another location instead,
most often the module that defines them. -
Some items have moved and need to be imported from a new location.
For example, here are the changes made to examples/add-timestamp-header/src/main.rs
:
-use apollo_router::{plugin::utils, Plugin, RouterRequest, RouterResponse};
+use apollo_router::plugin::test;
+use apollo_router::plugin::Plugin;
+use apollo_router::services::{RouterRequest, RouterResponse};
-let mut mock = utils::test::MockRouterService::new();
+let mut mock = test::MockRouterService::new();
-if let apollo_router::ResponseBody::GraphQL(response) =
+if let apollo_router::services::ResponseBody::GraphQL(response) =
service_response.next_response().await.unwrap()
{
If you're unsure where a given item needs to be imported from when porting code,
unfold the listing below and use your browser's search function (CTRL+F or ⌘+F).
Output of ./scripts/public_items.sh
for 0.10.0
use apollo_router::ApolloRouter; use apollo_router::Configuration; use apollo_router::ConfigurationKind; use apollo_router::Context; use apollo_router::Error; use apollo_router::Executable; use apollo_router::Request; use apollo_router::Response; use apollo_router::Schema; use apollo_router::SchemaKind; use apollo_router::ShutdownKind; use apollo_router::error::CacheResolverError; use apollo_router::error::FetchError; use apollo_router::error::JsonExtError; use apollo_router::error::Location; use apollo_router::error::ParseErrors; use apollo_router::error::PlannerErrors; use apollo_router::error::QueryPlannerError; use apollo_router::error::SchemaError; use apollo_router::error::ServiceBuildError; use apollo_router::error::SpecError; use apollo_router::graphql::Error; use apollo_router::graphql::NewErrorBuilder; use apollo_router::graphql::Request; use apollo_router::graphql::Response; use apollo_router::json_ext::Object; use apollo_router::json_ext::Path; use apollo_router::json_ext::PathElement; use apollo_router::layers::ServiceBuilderExt; use apollo_router::layers::ServiceExt; use apollo_router::layers::async_checkpoint::AsyncCheckpointLayer; use apollo_router::layers::async_checkpoint::AsyncCheckpointService; use apollo_router::layers::cache::CachingLayer; use apollo_router::layers::cache::CachingService; use apollo_router::layers::instrument::InstrumentLayer; use apollo_router::layers::instrument::InstrumentService; use apollo_router::layers::map_future_with_context::MapFutureWithContextLayer; use apollo_router::layers::map_future_with_context::MapFutureWithContextService; use apollo_router::layers::sync_checkpoint::CheckpointLayer; use apollo_router::layers::sync_checkpoint::CheckpointService; use apollo_router::main; use apollo_router::mock_service; use apollo_router::plugin::DynPlugin; use apollo_router::plugin::Handler; use apollo_router::plugin::Plugin; use apollo_router::plugin::PluginFactory; use apollo_router::plugin::plugins; use apollo_router::plugin::register_plugin; use apollo_router::plugin::serde::deserialize_header_name; use apollo_router::plugin::serde::deserialize_header_value; use apollo_router::plugin::serde::deserialize_option_header_name; use apollo_router::plugin::serde::deserialize_option_header_value; use apollo_router::plugin::serde::deserialize_regex; use apollo_router::plugin::test::IntoSchema; use apollo_router::plugin::test::MockExecutionService; use apollo_router::plugin::test::MockQueryPlanningService; use apollo_router::plugin::test::MockRouterService; use apollo_router::plugin::test::MockSubgraph; use apollo_router::plugin::test::MockSubgraphService; use apollo_router::plugin::test::NewPluginTestHarnessBuilder; use apollo_router::plugin::test::PluginTestHarness; use apollo_router::plugins::csrf::CSRFConfig; use apollo_router::plugins::csrf::Csrf; use apollo_router::plugins::rhai::Conf; use apollo_router::plugins::rhai::Rhai; use apollo_router::plugins::telemetry::ROUTER_SPAN_NAME; use apollo_router::plugins::telemetry::Telemetry; use apollo_router::plugins::telemetry::apollo::Config; use apollo_router::plugins::telemetry::config::AttributeArray; use apollo_router::plugins::telemetry::config::AttributeValue; use apollo_router::plugins::telemetry::config::Conf; use apollo_router::plugins::telemetry::config::GenericWith; use apollo_router::plugins::telemetry::config::Metrics; use apollo_router::plugins::telemetry::config::MetricsCommon; use apollo_router::plugins::telemetry::config::Propagation; use apollo_router::plugins::telemetry::config::Sampler; use apollo_router::plugins::telemetry::config::SamplerOption; use apollo_router::plugins::telemetry::config::Trace; use apollo_router::plugins::telemetry::config::Tracing; use apollo_router::query_planner::OperationKind; use apollo_router::query_planner::QueryPlan; use apollo_router::query_planner::QueryPlanOptions; use apollo_router::register_plugin; use apollo_router::services::ErrorNewExecutionResponseBuilder; use apollo_router::services::ErrorNewQueryPlannerResponseBuilder; use apollo_router::services::ErrorNewRouterResponseBuilder; use apollo_router::services::ErrorNewSubgraphResponseBuilder; use apollo_router::services::ExecutionRequest; use apollo_router::services::ExecutionResponse; use apollo_router::services::ExecutionService; use apollo_router::services::FakeNewExecutionRequestBuilder; use apollo_router::services::FakeNewExecutionResponseBuilder; use apollo_router::services::FakeNewRouterRequestBuilder; use apollo_router::services::FakeNewRouterResponseBuilder; use apollo_router::services::FakeNewSubgraphRequestBuilder; use apollo_router::services::FakeNewSubgraphResponseBuilder; use apollo_router::services::NewExecutionRequestBuilder; use apollo_router::services::NewExecutionResponseBuilder; use apollo_router::services::NewExecutionServiceBuilder; use apollo_router::services::NewQueryPlannerRequestBuilder; use apollo_router::services::NewQueryPlannerResponseBuilder; use apollo_router::services::NewRouterRequestBuilder; use apollo_router::services::NewRouterResponseBuilder; use apollo_router::services::NewRouterServiceBuilder; use apollo_router::services::NewSubgraphRequestBuilder; use apollo_router::services::NewSubgraphResponseBuilder; use apollo_router::services::PluggableRouterServiceBuilder; use apollo_router::services::QueryPlannerContent; use apollo_router::services::QueryPlannerRequest; use apollo_router::services::QueryPlannerResponse; use apollo_router::services::ResponseBody; use apollo_router::services::RouterRequest; use apollo_router::services::RouterResponse; use apollo_router::services::RouterService; use apollo_router::services::SubgraphRequest; use apollo_router::services::SubgraphResponse; use apollo_router::services::SubgraphService; use apollo_router::services::http_ext::FakeNewRequestBuilder; use apollo_router::services::http_ext::IntoHeaderName; use apollo_router::services::http_ext::IntoHeaderValue; use apollo_router::services::http_ext::NewRequestBuilder; use apollo_router::services::http_ext::Request; use apollo_router::services::http_ext::Response; use apollo_router::subscriber::RouterSubscriber; use apollo_router::subscriber::is_global_subscriber_set; use apollo_router::subscriber::replace_layer; use apollo_router::subscriber::set_global_subscriber;
By @SimonSapin
Entry point impr...
v0.9.5
❗ BREAKING ❗
Move experimental.traffic_shaping
out of experimental
PR #1229
You will need to update your YAML configuration file to use the correct name for traffic_shaping
plugin.
- plugins:
- experimental.traffic_shaping:
- variables_deduplication: true # Enable the variables deduplication optimization
- all:
- query_deduplication: true # Enable query deduplication for all subgraphs.
- subgraphs:
- products:
- query_deduplication: false # Disable query deduplication for products.
+ traffic_shaping:
+ variables_deduplication: true # Enable the variables deduplication optimization
+ all:
+ query_deduplication: true # Enable query deduplication for all subgraphs.
+ subgraphs:
+ products:
+ query_deduplication: false # Disable query deduplication for products.
Rhai plugin request.sub_headers
renamed to request.subgraph.headers
PR #1261
Rhai scripts previously supported the request.sub_headers
attribute so that subgraph request headers could be
accessed. This is now replaced with an extended interface for subgraph requests:
request.subgraph.headers
request.subgraph.body.query
request.subgraph.body.operation_name
request.subgraph.body.variables
request.subgraph.body.extensions
request.subgraph.uri.host
request.subgraph.uri.path
🚀 Features
Add support of compression PR #1229
Add support of request and response compression for the router and all subgraphs. The router is now able to handle Content-Encoding
and Accept-Encoding
headers properly. Supported algorithms are gzip
, br
, deflate
.
You can also enable compression on subgraphs requests and responses by updating the traffic_shaping
configuration:
traffic_shaping:
all:
compression: br # Enable brotli compression for all subgraphs
subgraphs:
products:
compression: gzip # Enable gzip compression only for subgraph products
Add support of multiple uplink URLs PR #1210
Add support of multiple uplink URLs with a comma-separated list in APOLLO_UPLINK_ENDPOINTS
and for --apollo-uplink-endpoints
Example:
export APOLLO_UPLINK_ENDPOINTS="https://aws.uplink.api.apollographql.com/, https://uplink.api.apollographql.com/"
Add support for adding extra environment variables and volumes to helm chart PR #1245
You can mount your supergraph.yaml
into the helm deployment via configmap. Using Kustomize to generate your configmap from your supergraph.yaml is suggested.
Example configmap.yaml snippet:
supergraph.yaml:
server:
listen: 0.0.0.0:80
Example helm config:
extraEnvVars:
- name: APOLLO_ROUTER_SUPERGRAPH_PATH
value: /etc/apollo/supergraph.yaml
# sets router log level to debug
- name: APOLLO_ROUTER_LOG
value: debug
extraEnvVarsCM: ''
extraEnvVarsSecret: ''
extraVolumes:
- name: supergraph-volume
configMap:
name: some-configmap
extraVolumeMounts:
- name: supergraph-volume
mountPath: /etc/apollo
By @LockedThread in #1245
🐛 Fixes
Support introspection object types (PR #1240)
Introspection queries can use a set of object types defined in the specification. The query parsing code was not recognizing them,
resulting in some introspection queries not working.
Update the scaffold template so that it works with streams (#1247)
Release v0.9.4 changed the way we deal with Response
objects, which can now be streams.
The scaffold template has been updated so that it generates plugins that are compatible with the new Plugin API.
By @o0Ignition0o in #1248
Create the ExecutionResponse
after the primary response was generated (PR #1260)
The @defer
preliminary work had a surprising side effect: when using methods like RouterResponse::map_response
, they were
executed before the subgraph responses were received, because they work on the stream of responses.
This PR goes back to the previous behaviour by awaiting the primary response before creating the ExecutionResponse
.
Use the API schema to generate selections (PR #1255)
When parsing the schema to generate selections for response formatting, we should use the API schema instead of the supergraph schema.
📚 Documentation
Update README link to the configuration file (PR #1208)
As the structure of the documentation has changed, the link should point to the YAML config file
section of the overview.
v0.9.4
❗ BREAKING ❗
Groundwork for @defer
support (PR #1175, PR #1206)
To prepare for the implementation of the @defer
directive, the ExecutionResponse
and RouterResponse
types now carry a stream of responses instead of a unique response. For now that stream contains only one item, so there is no change in behaviour. However, the Plugin trait changed to accomodate this, so a couple of steps are required to migrate your plugin so it is compatible with router v0.9.4:
- Add a dependency to futures in your Cargo.toml:
+futures = "0.3.21"
- Import
BoxStream
, and if your Plugin defines arouter_service
behavior, importResponseBody
:
+ use futures::stream::BoxStream;
+ use apollo_router::ResponseBody;
- Update the
router_service
and theexecution_service
sections of your Plugin (if applicable):
fn router_service(
&mut self,
- service: BoxService<RouterRequest, RouterResponse, BoxError>,
- ) -> BoxService<RouterRequest, RouterResponse, BoxError> {
+ service: BoxService<RouterRequest, RouterResponse<BoxStream<'static, ResponseBody>>, BoxError>,
+ ) -> BoxService<RouterRequest, RouterResponse<BoxStream<'static, ResponseBody>>, BoxError> {
[...]
fn execution_service(
&mut self,
- service: BoxService<ExecutionRequest, ExecutionResponse, BoxError>,
- ) -> BoxService<ExecutionRequest, ExecutionResponse, BoxError> {
+ service: BoxService<ExecutionRequest, ExecutionResponse<BoxStream<'static, Response>>, BoxError>,
+ ) -> BoxService<ExecutionRequest, ExecutionResponse<BoxStream<'static, Response>>, BoxError> {
We can now update our unit tests so they work on a stream of responses instead of a single one:
// Send a request
- let result = test_harness.call_canned().await?;
- if let ResponseBody::GraphQL(graphql) = result.response.body() {
+ let mut result = test_harness.call_canned().await?;
+
+ let first_response = result
+ .next_response()
+ .await
+ .expect("couldn't get primary response");
+
+ if let ResponseBody::GraphQL(graphql) = first_response {
assert!(graphql.data.is_some());
} else {
panic!("expected graphql response")
}
+ // You could keep calling result.next_response() until it yields None if you are expexting more parts.
+ assert!(result.next_response().await.is_none());
Ok(())
}
The apollo-router-core
crate has been merged into apollo-router
(PR #1189)
To upgrade, remove any dependency on the apollo-router-core
crate from your Cargo.toml
files and change imports like so:
- use apollo_router_core::prelude::*;
+ use apollo_router::prelude::*;
By @SimonSapin in #1189
Fix input validation rules (PR #1211)
The GraphQL specification provides two sets of coercion / validation rules, depending on whether we're dealing with inputs or outputs.
We have added validation rules for specified input validations which were not previously implemented.
This is a breaking change since slightly invalid input may have validated before but will now be guarded by newly-introduced validation rules.
By @o0Ignition0o in #1211
🚀 Features
Add trace logs for parsing recursion consumption (PR #1222)
The apollo-parser
package now implements recursion limits which can be examined after the parsing phase. The router logs these
out at trace
level. You can see them in your logs by searching for "recursion_limit
". For example, when using JSON logging
and using jq
to filter the output:
router -s ../graphql/supergraph.graphql -c ./router.yaml --log trace | jq -c '. | select(.fields.message == "recursion limit data")'
{"timestamp":"2022-06-10T15:01:02.213447Z","level":"TRACE","fields":{"message":"recursion limit data","recursion_limit":"recursion limit: 4096, high: 0"},"target":"apollo_router::spec::schema"}
{"timestamp":"2022-06-10T15:01:02.261092Z","level":"TRACE","fields":{"message":"recursion limit data","recursion_limit":"recursion limit: 4096, high: 0"},"target":"apollo_router::spec::schema"}
{"timestamp":"2022-06-10T15:01:07.642977Z","level":"TRACE","fields":{"message":"recursion limit data","recursion_limit":"recursion limit: 4096, high: 4"},"target":"apollo_router::spec::query"}
This example output shows that the maximum recursion limit is 4096 and that the query we processed caused us to recurse 4 times.
Helm chart now has the option to use an existing secrets for API key (PR #1196)
This change allows the use of an already existing secret for the graph API key.
To use existing secrets, update your own values.yaml
file or specify the value on your helm install
command line. For example:
helm install --set router.managedFederation.existingSecret="my-secret-name" <etc...>`
By @pellizzetti in #1196
Add iterators to Context
(PR #1202)
Context can now be iterated over, with two new methods:
iter()
iter_mut()
These implementations lean heavily on an underlying DashMap
implemetation, so refer to its documentation for more usage details.
Add an experimental optimization to deduplicate variables in query planner (PR #872)
Get rid of duplicated variables in requests and responses of the query planner. This optimization is disabled by default, if you want to enable it you just need override your configuration:
plugins:
experimental.traffic_shaping:
variables_deduplication: true # Enable the variables deduplication optimization
Add more customizable metrics (PR #1159)
Added the ability to apply custom attributes/labels to metrics which are derived from header values using the Router's configuration file. For example:
telemetry:
metrics:
common:
attributes:
static:
- name: "version"
value: "v1.0.0"
from_headers:
- named: "content-type"
rename: "payload_type"
default: "application/json"
- named: "x-custom-header-to-add"
Allow to set a custom health check path (PR #1164)
Added the possibility to set a custom health check path
server:
# Default is /.well-known/apollo/server-health
health_check_path: /health
🐛 Fixes
Pin clap
dependency in Cargo.toml
(PR #1232)
A minor release of Clap
occured yesterday which introduced a breaking change. This change might lead cargo scaffold
users to hit a panic a runtime when the router tries to parse environment variables and arguments.
This patch pins the clap
dependency to the version that was available before the release, until the root cause is found and fixed upstream.
By @o0Ignition0o in #1232
Display better error message when on subgraph fetch errors (PR #1201)
Show a helpful error message when a subgraph does not return JSON or a bad status code
Fix CORS configuration to eliminate runtime panic on misconfiguration (PR #1197)
Previously, it was possible to specify a CORS configuration which was syntactically valid, but which could not be enforced at runtime. For example, consider the following invalid configuration where the allow_any_origin
and allow_credentials
parameters are inherantly incompatible with each other (per the CORS specification):
server:
cors:
allow_any_origin: true
allow_credentials: true
Previously, this would result in a runtime panic. The router will now detect this kind of misconfiguration and report the error without panicking.
🛠 Maintenance
Groundwork for @defer
support (PR #1175PR #1206)
To prepare for the implementation of the @defer
directive, the ExecutionResponse
and RouterResponse
types now carry a stream of responses instead of a unique response. For now that stream contains only one item, so there is no change in behaviour.
Fix a flappy test to test custom health check path (PR #1176)
Force the cre...