🚀 Features
Update to Federation v2.3.0 (Issue #2465, Issue #2485 and Issue #2489)
This brings in Federation v2.3.0 execution support for:
@interfaceObject
(added to federation in federation#2277).- the bug fix from federation#2294.
By @abernix and @o0Ignition0o in #2462
By @pcmanus in #2485 and #2489
Always deduplicate variables on subgraph entity fetches (Issue #2387)
Variable deduplication allows the router to reduce the number of entities that are requested from subgraphs if some of them are redundant, and as such reduce the size of subgraph responses. It has been available for a while but was not active by default. This is now always on.
Add optional Access-Control-Max-Age
header to CORS plugin (Issue #2212)
Adds new option called max_age
to the existing cors
object which will set the value returned in the Access-Control-Max-Age
header. As was the case previously, when this value is not set no value is returned.
It can be enabled using our standard time notation, as follows:
cors:
max_age: 1day
By @osamra-rbi in #2331
Improved support for wildcards in supergraph.path
configuration (Issue #2406)
You can now use a wildcard in supergraph endpoint path
like this:
supergraph:
listen: 0.0.0.0:4000
path: /graph*
In this example, the Router would respond to requests on both /graphql
and /graphiql
.
🐛 Fixes
Forbid caching PERSISTED_QUERY_NOT_FOUND
responses (Issue #2502)
The router now sends a cache-control: private, no-cache, must-revalidate
response header to clients, in addition to the existing PERSISTED_QUERY_NOT_FOUND
error code on the response which was being sent previously. This expanded behaviour occurs when a persisted query hash could not be found and is important since such responses should not be cached by intermediary proxies/CDNs since the client will need to be able to send the full query directly to the Router on a subsequent request.
By @o0Ignition0o in #2503
Listen on root URL when /*
is set in supergraph.path
configuration (Issue #2471)
This resolves a regression which occurred in Router 1.8 when using wildcard notation on a path-boundary, as such:
supergraph:
path: /*
This occurred due to an underlying Axum upgrade and resulted in failure to listen on localhost
when a path was absent. We now special case /*
to also listen to the URL without a path so you're able to call http://localhost
(for example).
Subgraph traffic shaping timeouts now return HTTP 504 status code (Issue #2360 Issue #2400)
There was a regression where timeouts resulted in a HTTP response of 500 Internal Server Error
. This is now fixed with a test to guarantee it, the status code is now 504 Gateway Timeout
(instead of the previous 408 Request Timeout
which, was also incorrect in that it blamed the client).
There is also a new metric emitted called apollo_router_timeout
to track when timeouts are triggered.
Fix panic in schema parse error reporting (Issue #2269)
In order to support introspection, some definitions like type __Field { … }
are implicitly added to schemas. This addition was done by string concatenation at the source level. In some cases, like unclosed braces, a parse error could be reported at a position beyond the size of the original source. This would cause a panic because only the unconcatenated string is sent to the error reporting library miette
.
Instead, the Router now parses introspection types separately and "concatenates" the definitions at the AST level.
By @SimonSapin in #2448
Always accept compressed subgraph responses (Issue #2415)
Previously, subgraph response decompression was only supported when subgraph request compression was explicitly configured. This is now always active.
Fix handling of root query operations not named Query
If you'd mapped your default Query
type to something other than the default using schema { query: OtherQuery }
, some parsing code in the Router would incorrectly return an error because it had previously assumed the default name of Query
. The same case would have occurred if the root mutation type was not named Mutation
.
This is now corrected and the Router understands the mapping.
By @SimonSapin in #2459
Remove the locations
field from subgraph errors (Issue #2297)
Subgraph errors can come with a locations
field indicating which part of the query was causing issues, but it refers to the subgraph query generated by the query planner, and we have no way of translating it to locations in the client query. To avoid confusion, we've removed this field from the response until we can provide a more coherent way to map these errors back to the original operation.
Emit metrics showing number of client connections (issue #2384)
New metrics are available to track the client connections:
apollo_router_session_count_total
indicates the number of currently connected clientsapollo_router_session_count_active
indicates the number of in flight GraphQL requests from connected clients.
This also fixes the behaviour when we reach the maximum number of file descriptors: instead of going into a busy loop, the router will wait a bit before accepting a new connection.
--dev
will no longer modify configuration that it does not directly touch (Issue #2404, Issue #2481)
Previously, the Router's --dev
mode was operating against the configuration object model. This meant that it would sometimes replace pieces of configuration where it should have merely modified it. Now, --dev
mode will override the following properties in the YAML config, but it will leave any adjacent configuration as it was:
homepage:
enabled: false
include_subgraph_errors:
all: true
plugins:
experimental.expose_query_plan: true
sandbox:
enabled: true
supergraph:
introspection: true
telemetry:
tracing:
experimental_response_trace_id:
enabled: true
By @BrynCooke in #2489
🛠 Maintenance
Improve #[serde(default)]
attribute on structs (Issue #2424)
If all the fields of your struct
have their default value then use the #[serde(default)]
on the struct
instead of on each field. If you have specific default values for a field, you'll have to create your own impl Default
for the struct
.
Correct approach
#[serde(deny_unknown_fields, default)]
struct Export {
url: Url,
enabled: bool
}
impl Default for Export {
fn default() -> Self {
Self {
url: default_url_fn(),
enabled: false
}
}
}
Discouraged approach
#[serde(deny_unknown_fields)]
struct Export {
#[serde(default="default_url_fn")
url: Url,
#[serde(default)]
enabled: bool
}
📃 Configuration
Configuration changes will be automatically migrated on load. However, you should update your source configuration files as these will become breaking changes in a future major release.
health-check
has been renamed to health_check
(Issue #2161)
The health_check
option in the configuration has been renamed to use snake_case
rather than kebab-case
for consistency with the other properties in the configuration:
-health-check:
+health_check:
enabled: true
By @BrynCooke in #2451 and #2463
📚 Documentation
Disabling anonymous usage metrics (Issue #2478)
To disable the anonymous usage metrics, you set APOLLO_TELEMETRY_DISABLED=true
in the environment. The documentation previously said to use 1
as the value instead of true
. In the future, either will work, so this is primarily a bandaid for the immediate error.
send_headers
and send_variable_values
in telemetry.apollo
(Issue #2149)
-
send_headers
Provide this field to configure which request header names and values are included in trace data that's sent to Apollo Studio. Valid options are:
only
with an array,except
with an array,none
,all
.The default value is `none``, which means no header names or values are sent to Studio. This is a security measure to prevent sensitive data from potentially reaching the Router.
-
send_variable_values
Provide this field to configure which variable values are included in trace data that's sent to Apollo Studio. Valid options are:
only
with an array,except
with an array,none
,all
.The default value is
none
, which means no variable values are sent to Studio. This is a security measure to prevent sensitive data from potentially reaching the Router.
Propagating headers between subgraphs (Issue #2128)
Passing headers between subgraph services is possible via Rhai script and we've added an example to the header propagation documentation.
By @BrynCooke in #2446
Propagating response headers to clients (Issue #1284)
Passing headers from subgraph services to clients is possible via Rhai script and we've added an example to the header propagation documentation.
By @lennyburdette in #2474
IPv6 listening instructions (Issue #1835)
Added instructions for how to represent IPv6 listening addresses to our Overview documentation.
supergraph:
# The socket address and port to listen on.
# Note that this must be quoted to avoid interpretation as a yaml array.
listen: '[::1]:4000'
By @BrynCooke in #2440
🛠 Maintenance
Parse schemas and queries with apollo-compiler
The Router now uses the higher-level representation (HIR) from apollo-compiler
instead of using the AST from apollo-parser
directly. This is a first step towards replacing a bunch of code that grew organically during the Router's early days, with a general-purpose library with intentional design. Internal data structures are unchanged for now. Parsing behavior has been tested to be identical on a large corpus of schemas and queries.
By @SimonSapin in #2466
Disregard value of APOLLO_TELEMETRY_DISABLED
in Orbiter unit tests (Issue #2487)
The orbiter::test::test_visit_args
tests were failing in the event that APOLLO_TELEMETRY_DISABLED
was set, however this is now corrected.
By @BrynCooke in #2488
🥼 Experimental
JWT authentication (Issue #912)
As a result of UX feedback, we are modifying the experimental JWT configuration. The jwks_url
parameter is renamed to jwks_urls
and now expects to receive an array of URLs, rather than a single URL.
We've updated the JWT Authentication documentation accordingly, however here's a short sample configuration example:
authentication:
experimental:
jwt:
jwks_urls:
- https://dev-abcd1234.us.auth0.com/.well-known/jwks.json